{"record":{"id":"54c6ee53eb06b485","repo":"apereo/cas","slug":"authentication-request-does-not-include-the-s","errorCode":null,"errorMessage":"Authentication request does not include the [{}] scope. CAS will not produce an ID token without this scope.","messagePattern":"Authentication request does not include the \\[(.+?)\\] scope\\. CAS will not produce an ID token without this scope\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/token/OidcIdTokenGeneratorService.java","lineNumber":88,"sourceCode":"    public OidcIdTokenGeneratorService(final ObjectProvider<OidcConfigurationContext> configurationContext) {\n        super(configurationContext);\n    }\n\n    private static void setClaim(final JwtClaims claims, final String claimName, final Object claimValue) {\n        if (claimValue != null && StringUtils.isNotBlank(claimValue.toString())) {\n            claims.setClaim(claimName, claimValue);\n        }\n    }\n\n    @Audit(action = AuditableActions.OIDC_ID_TOKEN,\n        actionResolverName = AuditActionResolvers.OIDC_ID_TOKEN_ACTION_RESOLVER,\n        resourceResolverName = AuditResourceResolvers.OIDC_ID_TOKEN_RESOURCE_RESOLVER)\n    @Override\n    public @Nullable OidcIdToken generate(final IdTokenGenerationContext context) throws Throwable {\n        Assert.isAssignable(OidcRegisteredService.class, context.getRegisteredService().getClass(),\n            \"Registered service instance is not registered as an OpenID Connect application\");\n        if (!context.getAccessToken().getScopes().contains(OidcConstants.StandardScopes.OPENID.getScope())) {\n            LOGGER.warn(\"Authentication request does not include the [{}] scope. CAS will not produce an ID token without this scope.\",\n                OidcConstants.StandardScopes.OPENID.getScope());\n            return null;\n        }\n        if (context.getGrantType() == OAuth20GrantTypes.JWT_BEARER\n            && !getConfigurationContext().getCasProperties().getAuthn().getOidc().getIdToken().isGenerateForJwtBearerGrantType()) {\n            LOGGER.debug(\"ID token generation for grant type [{}] is disabled. Skipping ID token generation.\", OAuth20GrantTypes.JWT_BEARER);\n            return null;\n        }\n\n        val claims = buildJwtClaims(context);\n        var deviceSecret = StringUtils.EMPTY;\n        if (context.getGrantType() == OAuth20GrantTypes.AUTHORIZATION_CODE\n            && context.getAccessToken().getScopes().contains(OidcConstants.StandardScopes.DEVICE_SSO.getScope())\n            && getConfigurationContext().getDiscoverySettings().isNativeSsoSupported()) {\n            deviceSecret = getConfigurationContext().getDeviceSecretGenerator().generate();\n            claims.setStringClaim(OidcConstants.DS_HASH, getConfigurationContext().getDeviceSecretGenerator().hash(deviceSecret));\n            if (context.getAccessToken().getTicketGrantingTicket() != null) {\n                val encoded = (byte[]) getConfigurationContext().getTicketRegistry().getCipherExecutor()","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/token/OidcIdTokenGeneratorService.java#L70-L106","documentation":"CAS only issues an OIDC ID token when the authorization request granted the 'openid' scope. If the access token tied to the IdTokenGenerationContext lacks the openid scope, ID token generation is skipped with this warning and a null token is returned, so the client receives no ID token.","triggerScenarios":"OidcIdTokenGeneratorService.generate is invoked (token endpoint, implicit/hybrid flow) and context.getAccessToken().getScopes() does not contain OidcConstants.StandardScopes.OPENID ('openid'); also fires when the registered service's scope filtering removed 'openid' from the granted scopes.","commonSituations":"Client app omits scope=openid from its authorize URL; the OIDC registered service definition's supportedScopes excludes 'openid'; client policy restricts the granted scopes; custom/integration code calls token generation with a token minted for a non-OpenID grant.","solutions":["Add scope=openid to the client's authorization request URL.","Ensure the OIDC registered service definition includes 'openid' in its supported scopes.","Verify the client's registered scope grant/policy allows openid.","If the client intentionally wants only an access token, this warning is expected; include openid or use a plain OAuth2 flow instead.","Confirm the flow passes IdTokenGenerationContext with the same access token that carries the granted scopes."],"exampleFix":"// before\nGET /cas/oidc/authorize?client_id=app&response_type=code&redirect_uri=...\n// after\nGET /cas/oidc/authorize?client_id=app&response_type=code&scope=openid%20profile&redirect_uri=...","handlingStrategy":"validation","validationCode":"// Before initiating the OIDC flow, assert the request includes the openid scope:\nboolean hasOpenidScope(String authorizeUrl) {\n    String decoded = java.net.URLDecoder.decode(authorizeUrl, java.nio.charset.StandardCharsets.UTF_8);\n    return decoded.matches(\".*scope=([^&]*\\\\bopenid\\\\b[^&]*).*\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include scope=openid in OIDC authorization requests.","Include 'openid' in each OIDC registered service definition's supported scopes.","Integration-test token issuance with a sample client to confirm an ID token is returned.","Document that ID tokens are only minted for OpenID-scoped requests."],"tags":["oidc","scope","id-token","configuration"],"backgroundTag":"missing-required-config-field","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"}