{"record":{"id":"15eec73683db8b35","repo":"spring-projects/spring-security","slug":"server-error-15eec7","errorCode":"server_error","errorMessage":"The token generator failed to generate the device code.","messagePattern":"The token generator failed to generate the device code\\.","errorType":"error_code","errorClass":"OAuth2AuthenticationException","httpStatus":400,"severity":"error","filePath":"oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceAuthorizationRequestAuthenticationProvider.java","lineNumber":150,"sourceCode":"\t\t\tthis.logger.trace(\"Validated device authorization request parameters\");\n\t\t}\n\n\t\t// @formatter:off\n\t\tDefaultOAuth2TokenContext.Builder tokenContextBuilder = DefaultOAuth2TokenContext.builder()\n\t\t\t\t.registeredClient(registeredClient)\n\t\t\t\t.principal(clientPrincipal)\n\t\t\t\t.authorizationServerContext(AuthorizationServerContextHolder.getContext())\n\t\t\t\t.authorizationGrantType(AuthorizationGrantType.DEVICE_CODE)\n\t\t\t\t.authorizationGrant(deviceAuthorizationRequestAuthentication);\n\t\t// @formatter:on\n\n\t\t// Generate a high-entropy string to use as the device code\n\t\tOAuth2TokenContext tokenContext = tokenContextBuilder.tokenType(DEVICE_CODE_TOKEN_TYPE).build();\n\t\tOAuth2DeviceCode deviceCode = this.deviceCodeGenerator.generate(tokenContext);\n\t\tif (deviceCode == null) {\n\t\t\tOAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR,\n\t\t\t\t\t\"The token generator failed to generate the device code.\", ERROR_URI);\n\t\t\tthrow new OAuth2AuthenticationException(error);\n\t\t}\n\n\t\tif (this.logger.isTraceEnabled()) {\n\t\t\tthis.logger.trace(\"Generated device code\");\n\t\t}\n\n\t\t// Generate a low-entropy string to use as the user code\n\t\ttokenContext = tokenContextBuilder.tokenType(USER_CODE_TOKEN_TYPE).build();\n\t\tOAuth2UserCode userCode = this.userCodeGenerator.generate(tokenContext);\n\t\tif (userCode == null) {\n\t\t\tOAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR,\n\t\t\t\t\t\"The token generator failed to generate the user code.\", ERROR_URI);\n\t\t\tthrow new OAuth2AuthenticationException(error);\n\t\t}\n\n\t\tif (this.logger.isTraceEnabled()) {\n\t\t\tthis.logger.trace(\"Generated user code\");\n\t\t}","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceAuthorizationRequestAuthenticationProvider.java#L132-L168","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nhttp.oauth2AuthorizationServer((authorizationServer) -> authorizationServer\n    .tokenGenerator(new JwtGenerator(jwkSourceEncoder)));\n// after\nhttp.oauth2AuthorizationServer((authorizationServer) -> authorizationServer\n    .tokenGenerator(new DelegatingOAuth2TokenGenerator(\n        new JwtGenerator(jwkSourceEncoder),\n        new OAuth2AccessTokenGenerator(),\n        new OAuth2RefreshTokenGenerator())));","handlingStrategy":"try-catch","validationCode":"OAuth2TokenGenerator<?> gen = authorizationServerSettingsCustomizer.getTokenGenerator();\nif (gen == null || !supportsDeviceCode(gen)) {\n    throw new IllegalStateException(\"No OAuth2TokenGenerator configured for device codes\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    return deviceAuthorizationEndpoint.process(request);\n} catch (OAuth2AuthenticationException e) {\n    if (OAuth2ErrorCodes.SERVER_ERROR.equals(e.getError().getErrorCode())) {\n        // generator misconfiguration; surface to operators\n        throw new IllegalStateException(\"Token generator returned no device code\", e);\n    }\n    throw e;\n}","preventionTips":["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."],"tags":["oauth2","device-flow","token-generator","server-error"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}