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
- Set cas.oidc.federation.role=TRUST_ANCHOR or INTERMEDIATE on the entity that must serve fetch-entity statements
- Serve fetch-entity only from the dedicated federation deployment (separate from the OP deployment)
- 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
- Align role setting with which endpoints are exposed per deployment
- Validate role/endpoint pairing in a startup assertion
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
- Federation role [ ] is not supported for OpenID Provider
- No metadata defined for entity
- No federation keys defined for entity
- OpenID provider requires authority hint(s)
- Intermediate requires authority hint(s)
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)