spring-projects/spring-security · error · OAuth2AuthenticationException
server_error
server_error
Error message
The token generator failed to generate the access token.
What it means
When refreshing tokens (grant_type=refresh_token), the provider requests a new access token from the composed OAuth2TokenGenerator. If generate() returns null for the ACCESS_TOKEN context — no supporting generator — a server_error OAuth2AuthenticationException with 'The token generator failed to generate the access token.' is thrown.
Source
Thrown at oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProvider.java:212
.authorizationServerContext(AuthorizationServerContextHolder.getContext())
.authorization(authorization)
.authorizedScopes(scopes)
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.authorizationGrant(refreshTokenAuthentication);
// @formatter:on
if (dPoPProof != null) {
tokenContextBuilder.put(OAuth2TokenContext.DPOP_PROOF_KEY, dPoPProof);
}
OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.from(authorization);
// ----- Access token -----
OAuth2TokenContext tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.ACCESS_TOKEN).build();
OAuth2Token generatedAccessToken = this.tokenGenerator.generate(tokenContext);
if (generatedAccessToken == null) {
OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR,
"The token generator failed to generate the access token.", ERROR_URI);
throw new OAuth2AuthenticationException(error);
}
if (this.logger.isTraceEnabled()) {
this.logger.trace("Generated access token");
}
OAuth2AccessToken accessToken = OAuth2AuthenticationProviderUtils.accessToken(authorizationBuilder,
generatedAccessToken, tokenContext);
// ----- Refresh token -----
OAuth2RefreshToken currentRefreshToken = refreshToken.getToken();
if (!registeredClient.getTokenSettings().isReuseRefreshTokens()) {
// @formatter:off
tokenContext = tokenContextBuilder
.tokenType(OAuth2TokenType.REFRESH_TOKEN)
.authorization(authorizationBuilder.build()) // Refresh token generator/customizer may need access to the access token
.build();
// @formatter:onView on GitHub (pinned to 96852e8860)
Solutions
- Use DelegatingOAuth2TokenGenerator(JwtGenerator, OAuth2AccessTokenGenerator, OAuth2RefreshTokenGenerator) to cover all formats.
- Match TokenSettings.getAccessTokenFormat() (SELF_CONTAINED/REFERENCE) of the RegisteredClient to the configured generators.
- Verify custom generators return non-null for ACCESS_TOKEN token-type contexts.
- Catch OAuth2AuthenticationException in the token endpoint and return the OAuth2Error (error=server_error) response.
Example fix
// before
.tokenGenerator(new OAuth2AccessTokenGenerator()) // client uses JWT
// after
.tokenGenerator(new DelegatingOAuth2TokenGenerator(
new JwtGenerator(encoder), new OAuth2AccessTokenGenerator())); Defensive patterns
Strategy: try-catch
Validate before calling
OAuth2TokenContext ctx = new OAuth2TokenContextBuilder()
.tokenType(OAuth2TokenType.ACCESS_TOKEN)
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.registeredClient(registeredClient).build();
if (tokenGenerator.generate(ctx) == null) {
throw new IllegalStateException("No generator produces access tokens for client " + registeredClient.getId());
} Try / catch
try {
Authentication result = provider.authenticate(refreshRequest);
} catch (OAuth2AuthenticationException e) {
if (OAuth2ErrorCodes.SERVER_ERROR.equals(e.getError().getErrorCode())) {
// inspect tokenGenerator configuration before retrying
throw new IllegalStateException("Access token generator unsupported for this client", e);
}
throw e;
} Prevention
- After upgrading Spring Authorization Server, re-verify custom tokenGenerator() wiring still covers all token types.
- Align each client's access token format setting with the deployed generator set.
- Exercise the refresh_token grant in CI.
When it happens
Trigger: OAuth2RefreshTokenAuthenticationProvider.authenticate() validating the refresh token and then generating: tokenGenerator.generate(access-token context) == null, typically because the configured generators don't match the client's access token format settings.
Common situations: Authorization server customized with tokenGenerator(new JwtGenerator(...)) only while the client's TokenSettings demand REFERENCE (opaque) tokens; vice versa with OAuth2AccessTokenGenerator only and SELF_CONTAINED required; upgrading Spring Authorization Server and dropping part of the default generator chain.
Related errors
- server_error
- SERVER_ERROR
- server_error
- server_error
- Unable to create an {OAuth2AuthorizedClientManager} bean. Ex
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/233d33de3d7a2f51.
Report an issue: GitHub.