spring-projects/spring-security · error · OAuth2AuthorizationCodeRequestAuthenticationException
SERVER_ERROR
SERVER_ERROR
Error message
The token generator failed to generate the authorization code.
What it means
In OAuth2AuthorizationConsentAuthenticationProvider.authenticate (the consent approval step of the authorization code flow), after recording consent the provider generates a new authorization code via the OAuth2AuthorizationCodeGenerator. If generation yields null, it throws OAuth2AuthorizationCodeRequestAuthenticationException with this SERVER_ERROR message, aborting the redirect back to the client.
Source
Thrown at oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationConsentAuthenticationProvider.java:242
throw createException(OAuth2ErrorCodes.ACCESS_DENIED, OAuth2ParameterNames.CLIENT_ID,
authorizationConsentAuthentication, registeredClient, authorizationRequest);
}
OAuth2AuthorizationConsent authorizationConsent = authorizationConsentBuilder.build();
if (currentAuthorizationConsent == null || !authorizationConsent.equals(currentAuthorizationConsent)) {
this.authorizationConsentService.save(authorizationConsent);
if (this.logger.isTraceEnabled()) {
this.logger.trace("Saved authorization consent");
}
}
OAuth2TokenContext tokenContext = createAuthorizationCodeTokenContext(authorizationConsentAuthentication,
registeredClient, authorization, authorizedScopes);
OAuth2AuthorizationCode authorizationCode = this.authorizationCodeGenerator.generate(tokenContext);
if (authorizationCode == null) {
OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR,
"The token generator failed to generate the authorization code.", ERROR_URI);
throw new OAuth2AuthorizationCodeRequestAuthenticationException(error, null);
}
if (this.logger.isTraceEnabled()) {
this.logger.trace("Generated authorization code");
}
OAuth2Authorization updatedAuthorization = OAuth2Authorization.from(authorization)
.authorizedScopes(authorizedScopes)
.token(authorizationCode)
.attributes((attrs) -> attrs.remove(OAuth2ParameterNames.STATE))
.build();
this.authorizationService.save(updatedAuthorization);
if (this.logger.isTraceEnabled()) {
this.logger.trace("Saved authorization");
}
String redirectUri = authorizationRequest.getRedirectUri();View on GitHub (pinned to 96852e8860)
Solutions
- Register the default OAuth2AuthorizationCodeGenerator or include it in your generator chain.
- Fix any custom OAuth2AuthorizationCodeGenerator so it returns a non-null OAuth2AuthorizationCode for consent-derived contexts.
- Verify createAuthorizationCodeTokenContext inputs (authorization, scopes) are populated so the generator recognizes the context.
- Revert recent authorization server config customizations to the defaults and re-apply incrementally.
Example fix
// before
class MyCodeGenerator implements OAuth2TokenGenerator<OAuth2AuthorizationCode> {
public OAuth2AuthorizationCode generate(OAuth2TokenContext ctx) { return null; }
}
// after
class MyCodeGenerator implements OAuth2TokenGenerator<OAuth2AuthorizationCode> {
public OAuth2AuthorizationCode generate(OAuth2TokenContext ctx) {
return new OAuth2AuthorizationCode(Base64.getUrlEncoder().withoutPadding()
.encodeToString(SecureRandom.getInstanceStrong().generateSeed(32)),
Instant.now().plus(5, ChronoUnit.MINUTES));
}
} Defensive patterns
Strategy: try-catch
Validate before calling
OAuth2AuthorizationCode code = authorizationCodeGenerator.generate(consentCodeContext);
if (code == null) {
throw new IllegalStateException("Consent flow cannot mint authorization code; check generator bean");
} Try / catch
try {
// POST /oauth2/authorize (consent approval)
} catch (OAuth2AuthorizationCodeRequestAuthenticationException ex) {
if (OAuth2ErrorCodes.SERVER_ERROR.equals(ex.getError().getErrorCode())) {
log.error("Consent approved but code generation failed: {}", ex.getError().getDescription());
}
throw ex;
} Prevention
- Include consent flow in integration tests whenever the token generator chain changes
- Keep the default authorization code generator wired into both authorization-request and consent providers
- Verify createAuthorizationCodeTokenContext receives a populated authorization and scopes
When it happens
Trigger: The user approves consent (POST to /oauth2/authorize) and the provider must mint a fresh authorization code, but the authorization code generator bean is absent, misconfigured, or a custom implementation returns null for the context.
Common situations: Same as the authorization-request variant: custom generator returning null, removed default generator bean, or broken delegation in a composite generator when customizing the authorization server.
Related errors
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/94ccda8f51ebaa84.
Report an issue: GitHub.