apereo/cas · error

invalid_request

invalid_request

Error message

CAS cannot accept the request given the issuer is invalid.

What it means

OidcVerifiableCredentialNonceEndpointController.handle issues a credential nonce (c_nonce) for verifiable credential issuance, but first validates the request issuer. If issuerService.validateIssuer fails for the VC nonce URL, the controller responds HTTP 400 'invalid_request' / 'Invalid issuer' instead of a nonce.

Solutions

  1. Call the nonce endpoint on the URL matching cas.authn.oidc.issuer exactly.
  2. Enable proper forwarded-header handling so validateIssuer sees the original scheme/host.
  3. Verify the issuer configuration includes the path prefix used by the deployment.

Example fix

// before
curl -X POST http://localhost:8443/cas/oidc/vc/nonce
// after
curl -X POST https://sso.example.org/cas/oidc/vc/nonce
Defensive patterns

Strategy: validation

Validate before calling

String nonceUrl = issuer + "/vc/nonce"; // derive from issuer
if (!URI.create(nonceUrl).getHost().equals(URI.create(issuer).getHost())) {
    throw new IllegalArgumentException("Nonce endpoint must be on the issuer host");
}

Try / catch

if (resp.status() == 400 && body.contains("Invalid issuer")) {
    throw new IllegalStateException("Call the nonce endpoint via the configured issuer URL");
}

Prevention

When it happens

Trigger: POST/GET to the VC nonce endpoint (VC_NONCE_URL) from a host/origin that does not match the configured OIDC issuer.

Common situations: Wallet callbacks hitting an internal hostname; misconfigured issuer path; load balancer terminating TLS and changing the scheme seen by CAS.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/4a38fbba7708b707. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-oidc-vc/src/main/java/org/apereo/cas/oidc/vc/issuer/web/OidcVerifiableCredentialNonceEndpointController.java:60

    /**
     * Handle response entity.
     *
     * @param httpRequest  the http request
     * @param httpResponse the http response
     * @return the response entity
     */
    @PostMapping(value = {
        '/' + OidcConstants.BASE_OIDC_URL + '/' + OidcConstants.VC_NONCE_URL,
        "/**/" + OidcConstants.VC_NONCE_URL
    }, consumes = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity handle(
        final HttpServletRequest httpRequest,
        final HttpServletResponse httpResponse) {

        val webContext = new JEEContext(httpRequest, httpResponse);
        if (!getConfigurationContext().getIssuerService().validateIssuer(webContext, List.of(OidcConstants.VC_NONCE_URL))) {
            LOGGER.warn("CAS cannot accept the request given the issuer is invalid.");
            val body = OAuth20Utils.getErrorResponseBody(OAuth20Constants.INVALID_REQUEST, "Invalid issuer");
            return ResponseEntity.badRequest().body(body);
        }
        val nonce = credentialNonceService.create();
        return ResponseEntity
            .ok()
            .body(Map.of(OidcConstants.C_NONCE, nonce.value(), OidcConstants.C_NONCE_EXPIRES_IN, nonce.expiresIn()));
    }

    /**
     * Handle errors.
     *
     * @param ex the ex
     * @return the response entity
     */
    @ExceptionHandler(Exception.class)
    @SuppressWarnings("UnusedMethod")
    private static ResponseEntity<String> handle(final Exception ex) {

View on GitHub (pinned to e7288fc434)