spring-projects/spring-security · error · OAuth2AuthenticationException
invalid_id_token
invalid_id_token
Error message
Missing (required) ID Token in Token Response for Client Registration: ${registrationId} What it means
OpenID Connect requires the token response to include an id_token in additionalParameters. When the token endpoint's response lacks it, the OIDC provider cannot build an OidcUser, so invalid_id_token is thrown with the registration id in the message.
Source
Thrown at oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProvider.java:158
.getAuthorizationResponse();
if (authorizationResponse.statusError()) {
OAuth2Error error = authorizationResponse.getError();
Assert.notNull(error, "error cannot be null when status is error");
throw new OAuth2AuthenticationException(error, error.toString());
}
if (!Objects.equals(authorizationResponse.getState(), authorizationRequest.getState())) {
OAuth2Error oauth2Error = new OAuth2Error(INVALID_STATE_PARAMETER_ERROR_CODE);
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
}
OAuth2AccessTokenResponse accessTokenResponse = getResponse(authorizationCodeAuthentication);
ClientRegistration clientRegistration = authorizationCodeAuthentication.getClientRegistration();
Map<String, Object> additionalParameters = accessTokenResponse.getAdditionalParameters();
if (!additionalParameters.containsKey(OidcParameterNames.ID_TOKEN)) {
OAuth2Error invalidIdTokenError = new OAuth2Error(INVALID_ID_TOKEN_ERROR_CODE,
"Missing (required) ID Token in Token Response for Client Registration: "
+ clientRegistration.getRegistrationId(),
null);
throw new OAuth2AuthenticationException(invalidIdTokenError, invalidIdTokenError.toString());
}
OidcIdToken idToken = createOidcToken(clientRegistration, accessTokenResponse);
validateNonce(authorizationRequest, idToken);
OidcUser oidcUser = this.userService.loadUser(new OidcUserRequest(clientRegistration,
accessTokenResponse.getAccessToken(), idToken, additionalParameters));
Assert.notNull(oidcUser, "oidcUser cannot be null");
Collection<? extends GrantedAuthority> mappedAuthorities = this.authoritiesMapper
.mapAuthorities(oidcUser.getAuthorities());
OAuth2LoginAuthenticationToken authenticationResult = new OAuth2LoginAuthenticationToken(
authorizationCodeAuthentication.getClientRegistration(),
authorizationCodeAuthentication.getAuthorizationExchange(), oidcUser, mappedAuthorities,
accessTokenResponse.getAccessToken(), accessTokenResponse.getRefreshToken());
authenticationResult.setDetails(authorizationCodeAuthentication.getDetails());
return authenticationResult;
}
private OAuth2AccessTokenResponse getResponse(OAuth2LoginAuthenticationToken authorizationCodeAuthentication) {
try {View on GitHub (pinned to 96852e8860)
Solutions
- Ensure the openid scope is requested: .scope("openid", "profile", "email") in the client registration.
- Verify the tokenUri/issuer actually belongs to an OIDC provider that returns id_token for the code flow.
- Check that no custom token response client strips additionalParameters from the response.
- If the provider is OAuth2-only, drop OIDC login and use plain OAuth2Login without OidcUserService.
Example fix
// before
registration.scope("read:user");
// after
registration.scope("openid", "profile", "email"); Defensive patterns
Strategy: validation
Validate before calling
// assert OIDC readiness at startup
ClientRegistration reg = ...;
Set<String> scopes = reg.getScopes();
if (reg.getAuthorizationGrantType() == AuthorizationGrantType.AUTHORIZATION_CODE
&& !scopes.contains("openid")) {
throw new IllegalStateException("OIDC login requires the 'openid' scope; registration "
+ reg.getRegistrationId() + " does not request it");
} Try / catch
catch (OAuth2AuthenticationException ex) { if ("invalid_id_token".equals(ex.getError().getErrorCode())) { log.error("Provider did not return id_token; is this an OIDC provider and is 'openid' scoped?"); } throw ex; } Prevention
- Always include the openid scope for OIDC client registrations.
- Confirm the provider is OIDC-compliant (has .well-known/openid-configuration).
- Don't override the token response client in ways that drop additionalParameters.
- Verify with a raw token-endpoint curl that id_token appears in the response.
When it happens
Trigger: Thrown in authenticate() when accessTokenResponse.getAdditionalParameters() does not contain OidcParameterNames.ID_TOKEN after a successful token exchange with an OIDC provider.
Common situations: Registration configured with scope=openid missing (so the OP issues a plain OAuth2 token, not an OIDC one), the OP not actually being an OIDC provider, a non-standard token endpoint that puts id_token elsewhere, or using authorization_code with a provider that only supports the implicit/hybrid flow.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/fc18984218190a3d.
Report an issue: GitHub.