apereo/cas · error

invalid_request

invalid_request

Error message

CAS cannot accept the request given the issuer is invalid.

What it means

OidcVerifiableCredentialTypeMetadataController.handle describes a credential configuration (by configurationId) for verifiable credentials. Before describing, it validates the request issuer against VC_CREDENTIAL_TYPE_URL; on failure it returns HTTP 400 'invalid_request' / 'Invalid issuer'.

Solutions

  1. Use the externally configured issuer host/path when requesting type metadata.
  2. Correct ingress/proxy Host and X-Forwarded-Proto headers.
  3. Ensure the configured issuer matches the URL scheme (https) and hostname presented by clients.

Example fix

// before
curl https://10.0.0.5/cas/oidc/vc/credential-types/UniversityDegree_JWT
// after
curl https://sso.example.org/cas/oidc/vc/credential-types/UniversityDegree_JWT
Defensive patterns

Strategy: validation

Validate before calling

// Derive type metadata URL from issuer, not from cached/internal hosts
String typeUrl = issuer + "/vc/credential-types/" + configurationId;
if (!typeUrl.startsWith(issuer)) throw new IllegalArgumentException("URL not under issuer");

Try / catch

if (resp.status() == 400 && body.contains("Invalid issuer")) {
    throw new IllegalStateException("Re-fetch issuer metadata and use its URLs");
}

Prevention

When it happens

Trigger: GET the credential type metadata endpoint with a valid path configurationId but from a request whose issuer/host does not match the configured OIDC issuer.

Common situations: Clients caching discovery metadata from one environment and reusing host URLs from another; DNS aliases (internal vs external names); missing Host header preservation behind ingress.

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/a8831b5b432a2eff. Report an issue: GitHub.

Appendix: source

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

    /**
     * Handle response entity.
     *
     * @param request  the request
     * @param response the response
     * @return the response entity
     */
    @GetMapping(value = {
        '/' + OidcConstants.BASE_OIDC_URL + '/' + OidcConstants.VC_CREDENTIAL_TYPE_URL + "/{configurationId}",
        "/**/" + OidcConstants.VC_CREDENTIAL_TYPE_URL + "/{configurationId}"},
        produces = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Handle OIDC credential configuration type request",
        description = "Handles requests for OIDC credential configuration type metadata",
        parameters = @Parameter(name = "configurationId", in = ParameterIn.PATH, description = "Configuration ID"))
    public ResponseEntity handle(final HttpServletRequest request, final HttpServletResponse response,
                                 @PathVariable final String configurationId) {
        val webContext = new JEEContext(request, response);
        if (!getConfigurationContext().getIssuerService().validateIssuer(webContext, List.of(OidcConstants.VC_CREDENTIAL_TYPE_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 body = metadataService.describeConfiguration(configurationId);
        return body == null
            ? ResponseEntity.notFound().build()
            : ResponseEntity.ok().body(body);
    }

}

View on GitHub (pinned to e7288fc434)