{"record":{"id":"429faba4efa8b558","repo":"apereo/cas","slug":"federation-role-s-is-not-supported-for-trust-an","errorCode":null,"errorMessage":"Federation role [%s] is not supported for Trust Anchor/Intermediate","messagePattern":"Federation role \\[(.+?)\\] is not supported for Trust Anchor/Intermediate","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-oidc-federation/src/main/java/org/apereo/cas/oidc/federation/web/OidcFetchFederationEndpointController.java","lineNumber":64,"sourceCode":"     * @param sub the entityId\n     * @param request  the request\n     * @param response the response\n     * @return the specific entity statement\n     */\n    @GetMapping('/' + OidcConstants.BASE_OIDC_URL + OidcConstants.FETCH_FEDERATION_URL)\n    @Operation(summary = \"Handle OIDC fetch federation request\",\n        description = \"Handles requests for the fetch federation endpoint\",\n        parameters = {\n            @Parameter(name = \"sub\", description = \"entityId\", required = true)\n        })\n    public ResponseEntity fetchEntityStatement(@RequestParam(value = \"sub\", required = false) final String sub,\n        final HttpServletRequest request, final HttpServletResponse response) throws Exception {\n\n        LOGGER.info(\"Building entity statement for subordinate: [{}]\", sub);\n\n        val role = oidcProperties.getFederation().getRole();\n        if (!role.isTrustAnchorOrIntermediate()) {\n            throw new IllegalArgumentException(\"Federation role [\" + role + \"] is not supported for Trust Anchor/Intermediate\");\n        }\n\n        val error = retrieveInvalidIssuerError(request, response, OidcConstants.FETCH_FEDERATION_URL);\n        if (error != null) {\n            return error;\n        }\n\n        if (StringUtils.isBlank(sub)) {\n            val body = OAuth20Utils.getErrorResponseBody(OAuth20Constants.INVALID_REQUEST, \"Invalid entity\");\n            return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST);\n        }\n\n        val foundSubordinate = subordinateRepository.getSubordinates().get(sub);\n        if (foundSubordinate == null) {\n            val body = OAuth20Utils.getErrorResponseBody(OAuth20Constants.INVALID_REQUEST, \"Invalid entity\");\n            return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST);\n        }\n        val serviceMetadata = foundSubordinate.getMetadata();","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-oidc-federation/src/main/java/org/apereo/cas/oidc/federation/web/OidcFetchFederationEndpointController.java#L46-L82","documentation":"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.","triggerScenarios":"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).","commonSituations":"Deployment reuses an OP role config but also exposes federation endpoints; role property left at default; copy-pasted OP configuration for a federation server.","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"],"exampleFix":"// before\ncas.oidc.federation.role=OPENID_PROVIDER\n// after\ncas.oidc.federation.role=TRUST_ANCHOR","handlingStrategy":"validation","validationCode":"if (!oidcProperties.getFederation().getRole().isTrustAnchorOrIntermediate()) {\n    throw new IllegalStateException(\"fetch-entity endpoint requires TRUST_ANCHOR or INTERMEDIATE role\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    return controller.fetchEntityStatement(sub, request, response);\n} catch (IllegalArgumentException e) {\n    return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body(\"Federation role unsupported\");\n}","preventionTips":["Align role setting with which endpoints are exposed per deployment","Validate role/endpoint pairing in a startup assertion"],"tags":["configuration","oidc-federation","invalid-role"],"backgroundTag":"unsupported-operation","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}