apereo/cas · warning
Authentication request does not include the
Error message
Authentication request does not include the [{}] scope. CAS will not produce an ID token without this scope. What it means
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.
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.
Example fix
// before GET /cas/oidc/authorize?client_id=app&response_type=code&redirect_uri=... // after GET /cas/oidc/authorize?client_id=app&response_type=code&scope=openid%20profile&redirect_uri=...
Defensive patterns
Strategy: validation
Validate before calling
// Before initiating the OIDC flow, assert the request includes the openid scope:
boolean hasOpenidScope(String authorizeUrl) {
String decoded = java.net.URLDecoder.decode(authorizeUrl, java.nio.charset.StandardCharsets.UTF_8);
return decoded.matches(".*scope=([^&]*\\bopenid\\b[^&]*).*");
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Unable to use 'none' as ID token signing algorithm
- Unable to use 'none' as ID token encryption algorithm
- Individual claims requested by OpenID scopes are forced to…
- Unable to use 'none' for the user-info signing algorithm
- Unable to use 'none' as user-info encryption algorithm
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/54c6ee53eb06b485.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/token/OidcIdTokenGeneratorService.java:88
public OidcIdTokenGeneratorService(final ObjectProvider<OidcConfigurationContext> configurationContext) {
super(configurationContext);
}
private static void setClaim(final JwtClaims claims, final String claimName, final Object claimValue) {
if (claimValue != null && StringUtils.isNotBlank(claimValue.toString())) {
claims.setClaim(claimName, claimValue);
}
}
@Audit(action = AuditableActions.OIDC_ID_TOKEN,
actionResolverName = AuditActionResolvers.OIDC_ID_TOKEN_ACTION_RESOLVER,
resourceResolverName = AuditResourceResolvers.OIDC_ID_TOKEN_RESOURCE_RESOLVER)
@Override
public @Nullable OidcIdToken generate(final IdTokenGenerationContext context) throws Throwable {
Assert.isAssignable(OidcRegisteredService.class, context.getRegisteredService().getClass(),
"Registered service instance is not registered as an OpenID Connect application");
if (!context.getAccessToken().getScopes().contains(OidcConstants.StandardScopes.OPENID.getScope())) {
LOGGER.warn("Authentication request does not include the [{}] scope. CAS will not produce an ID token without this scope.",
OidcConstants.StandardScopes.OPENID.getScope());
return null;
}
if (context.getGrantType() == OAuth20GrantTypes.JWT_BEARER
&& !getConfigurationContext().getCasProperties().getAuthn().getOidc().getIdToken().isGenerateForJwtBearerGrantType()) {
LOGGER.debug("ID token generation for grant type [{}] is disabled. Skipping ID token generation.", OAuth20GrantTypes.JWT_BEARER);
return null;
}
val claims = buildJwtClaims(context);
var deviceSecret = StringUtils.EMPTY;
if (context.getGrantType() == OAuth20GrantTypes.AUTHORIZATION_CODE
&& context.getAccessToken().getScopes().contains(OidcConstants.StandardScopes.DEVICE_SSO.getScope())
&& getConfigurationContext().getDiscoverySettings().isNativeSsoSupported()) {
deviceSecret = getConfigurationContext().getDeviceSecretGenerator().generate();
claims.setStringClaim(OidcConstants.DS_HASH, getConfigurationContext().getDeviceSecretGenerator().hash(deviceSecret));
if (context.getAccessToken().getTicketGrantingTicket() != null) {
val encoded = (byte[]) getConfigurationContext().getTicketRegistry().getCipherExecutor()View on GitHub (pinned to e7288fc434)