spring-projects/spring-security · error · OAuth2AuthenticationException
server_error
server_error
Error message
The token generator failed to generate the device code.
What it means
During the OAuth 2.0 Device Authorization Grant flow, the provider asks the configured deviceCodeGenerator (OAuth2TokenGenerator) for an OAuth2DeviceCode. If the generator returns null — meaning no generator in the composed chain supports the DEVICE_CODE token type — the server cannot proceed and throws a server_error OAuth2AuthenticationException.
Source
Thrown at oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceAuthorizationRequestAuthenticationProvider.java:150
this.logger.trace("Validated device authorization request parameters");
}
// @formatter:off
DefaultOAuth2TokenContext.Builder tokenContextBuilder = DefaultOAuth2TokenContext.builder()
.registeredClient(registeredClient)
.principal(clientPrincipal)
.authorizationServerContext(AuthorizationServerContextHolder.getContext())
.authorizationGrantType(AuthorizationGrantType.DEVICE_CODE)
.authorizationGrant(deviceAuthorizationRequestAuthentication);
// @formatter:on
// Generate a high-entropy string to use as the device code
OAuth2TokenContext tokenContext = tokenContextBuilder.tokenType(DEVICE_CODE_TOKEN_TYPE).build();
OAuth2DeviceCode deviceCode = this.deviceCodeGenerator.generate(tokenContext);
if (deviceCode == null) {
OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR,
"The token generator failed to generate the device code.", ERROR_URI);
throw new OAuth2AuthenticationException(error);
}
if (this.logger.isTraceEnabled()) {
this.logger.trace("Generated device code");
}
// Generate a low-entropy string to use as the user code
tokenContext = tokenContextBuilder.tokenType(USER_CODE_TOKEN_TYPE).build();
OAuth2UserCode userCode = this.userCodeGenerator.generate(tokenContext);
if (userCode == null) {
OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR,
"The token generator failed to generate the user code.", ERROR_URI);
throw new OAuth2AuthenticationException(error);
}
if (this.logger.isTraceEnabled()) {
this.logger.trace("Generated user code");
}View on GitHub (pinned to 96852e8860)
Solutions
- Ensure the authorization server's OAuth2TokenGenerator includes a generator supporting OAuth2DeviceCode (e.g. keep the default composite or add OAuth2DeviceCodeGenerator via OAuth2AuthorizationServerConfigurer).
- If using a custom tokenGenerator(), delegate to a generator that handles DEVICE_CODE_TOKEN_TYPE, or return a non-null device code for that context.
- Inspect your custom generator's generate(): it must not return null for tokenType OAuth2ParameterNames.DEVICE_CODE contexts; throw or generate instead.
- Catch OAuth2AuthenticationException and surface error=server_error to the device client so it can retry.
Example fix
// before
http.oauth2AuthorizationServer((authorizationServer) -> authorizationServer
.tokenGenerator(new JwtGenerator(jwkSourceEncoder)));
// after
http.oauth2AuthorizationServer((authorizationServer) -> authorizationServer
.tokenGenerator(new DelegatingOAuth2TokenGenerator(
new JwtGenerator(jwkSourceEncoder),
new OAuth2AccessTokenGenerator(),
new OAuth2RefreshTokenGenerator()))); Defensive patterns
Strategy: try-catch
Validate before calling
OAuth2TokenGenerator<?> gen = authorizationServerSettingsCustomizer.getTokenGenerator();
if (gen == null || !supportsDeviceCode(gen)) {
throw new IllegalStateException("No OAuth2TokenGenerator configured for device codes");
} Try / catch
try {
return deviceAuthorizationEndpoint.process(request);
} catch (OAuth2AuthenticationException e) {
if (OAuth2ErrorCodes.SERVER_ERROR.equals(e.getError().getErrorCode())) {
// generator misconfiguration; surface to operators
throw new IllegalStateException("Token generator returned no device code", e);
}
throw e;
} Prevention
- Keep the default composite OAuth2TokenGenerator unless you must customize; when customizing, wrap existing generators with DelegatingOAuth2TokenGenerator.
- Write an integration test exercising the device authorization endpoint after any tokenGenerator() change.
- Never return null from custom generators; throw an UnsupportedOperationException for unsupported token types instead.
When it happens
Trigger: Calling OAuth2DeviceAuthorizationRequestAuthenticationProvider.authenticate() when the DeviceClientAuthenticationProvider/authorization server settings have no OAuth2TokenGenerator able to produce an OAuth2DeviceCode for tokenType DEVICE_CODE_TOKEN_TYPE (generator chain returns null).
Common situations: Customizing OAuth2Configurer tokenGenerator()/authorizationServerSettings and replacing the default composite generator without a device-code-capable generator; a custom generator that returns null for unrecognized contexts; narrowing the generator set so OAuth2DeviceCodeGenerator is excluded.
Related errors
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/15eec73683db8b35.
Report an issue: GitHub.