apereo/cas · error · IllegalArgumentException

Federation role [ ] is not supported for Trust…

Error message

Federation role [%s] is not supported for Trust Anchor/Intermediate

What it means

The fetch-entity JWKS endpoint builds entity statements for subordinates, which only a Trust Anchor or Intermediate can issue. If cas.oidc.federation.role is OPENID_PROVIDER, isTrustAnchorOrIntermediate() is false and the controller throws this IllegalArgumentException before processing the request.

Solutions

  1. Set cas.oidc.federation.role=TRUST_ANCHOR or INTERMEDIATE on the entity that must serve fetch-entity statements
  2. Serve fetch-entity only from the dedicated federation deployment (separate from the OP deployment)
  3. Check role via the resolved OidcFederationRole in startup logs/config before exposing the endpoint

Example fix

// before
cas.oidc.federation.role=OPENID_PROVIDER
// after
cas.oidc.federation.role=TRUST_ANCHOR
Defensive patterns

Strategy: validation

Validate before calling

if (!oidcProperties.getFederation().getRole().isTrustAnchorOrIntermediate()) {
    throw new IllegalStateException("fetch-entity endpoint requires TRUST_ANCHOR or INTERMEDIATE role");
}

Try / catch

try {
    return controller.fetchEntityStatement(sub, request, response);
} catch (IllegalArgumentException e) {
    return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body("Federation role unsupported");
}

Prevention

When it happens

Trigger: HTTP call to the federation fetch endpoint while the deployment's OidcFederationProperties role is set to OPENID_PROVIDER (or any role that is not trust-anchor/intermediate).

Common situations: Deployment reuses an OP role config but also exposes federation endpoints; role property left at default; copy-pasted OP configuration for a federation server.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at support/cas-server-support-oidc-federation/src/main/java/org/apereo/cas/oidc/federation/web/OidcFetchFederationEndpointController.java:64

     * @param sub the entityId
     * @param request  the request
     * @param response the response
     * @return the specific entity statement
     */
    @GetMapping('/' + OidcConstants.BASE_OIDC_URL + OidcConstants.FETCH_FEDERATION_URL)
    @Operation(summary = "Handle OIDC fetch federation request",
        description = "Handles requests for the fetch federation endpoint",
        parameters = {
            @Parameter(name = "sub", description = "entityId", required = true)
        })
    public ResponseEntity fetchEntityStatement(@RequestParam(value = "sub", required = false) final String sub,
        final HttpServletRequest request, final HttpServletResponse response) throws Exception {

        LOGGER.info("Building entity statement for subordinate: [{}]", sub);

        val role = oidcProperties.getFederation().getRole();
        if (!role.isTrustAnchorOrIntermediate()) {
            throw new IllegalArgumentException("Federation role [" + role + "] is not supported for Trust Anchor/Intermediate");
        }

        val error = retrieveInvalidIssuerError(request, response, OidcConstants.FETCH_FEDERATION_URL);
        if (error != null) {
            return error;
        }

        if (StringUtils.isBlank(sub)) {
            val body = OAuth20Utils.getErrorResponseBody(OAuth20Constants.INVALID_REQUEST, "Invalid entity");
            return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST);
        }

        val foundSubordinate = subordinateRepository.getSubordinates().get(sub);
        if (foundSubordinate == null) {
            val body = OAuth20Utils.getErrorResponseBody(OAuth20Constants.INVALID_REQUEST, "Invalid entity");
            return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST);
        }
        val serviceMetadata = foundSubordinate.getMetadata();

View on GitHub (pinned to e7288fc434)