{"record":{"id":"447879e3a5630e5e","repo":"spring-projects/spring-security","slug":"server-error-447879","errorCode":"server_error","errorMessage":"The token generator failed to generate the access token.","messagePattern":"The token generator failed to generate the access token\\.","errorType":"error_code","errorClass":"OAuth2AuthenticationException","httpStatus":500,"severity":"error","filePath":"oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationProvider.java","lineNumber":245,"sourceCode":"\t\t\t\t.authorization(subjectAuthorization)\n\t\t\t\t.principal(principal)\n\t\t\t\t.authorizationServerContext(AuthorizationServerContextHolder.getContext())\n\t\t\t\t.authorizedScopes(authorizedScopes)\n\t\t\t\t.tokenType(OAuth2TokenType.ACCESS_TOKEN)\n\t\t\t\t.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)\n\t\t\t\t.authorizationGrant(tokenExchangeAuthentication);\n\t\t// @formatter:on\n\t\tif (dPoPProof != null) {\n\t\t\ttokenContextBuilder.put(OAuth2TokenContext.DPOP_PROOF_KEY, dPoPProof);\n\t\t}\n\n\t\t// ----- Access token -----\n\t\tOAuth2TokenContext tokenContext = tokenContextBuilder.build();\n\t\tOAuth2Token generatedAccessToken = this.tokenGenerator.generate(tokenContext);\n\t\tif (generatedAccessToken == null) {\n\t\t\tOAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR,\n\t\t\t\t\t\"The token generator failed to generate the access token.\", 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 access token\");\n\t\t}\n\n\t\t// @formatter:off\n\t\tOAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.withRegisteredClient(registeredClient)\n\t\t\t\t.principalName(subjectAuthorization.getPrincipalName())\n\t\t\t\t.authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE)\n\t\t\t\t.authorizedScopes(authorizedScopes)\n\t\t\t\t.attribute(Principal.class.getName(), principal);\n\t\t// @formatter:on\n\n\t\tOAuth2AccessToken accessToken = OAuth2AuthenticationProviderUtils.accessToken(authorizationBuilder,\n\t\t\t\tgeneratedAccessToken, tokenContext);\n\n\t\tOAuth2Authorization authorization = authorizationBuilder.build();","sourceCodeStart":227,"sourceCodeEnd":263,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationProvider.java#L227-L263","documentation":"In the token-exchange grant flow, after validating the request the provider asks the configured OAuth2TokenGenerator to produce an access token for the built OAuth2TokenContext. A null result means no registered generator (e.g. JWT encoder or opaque-token generator) supports the context, so the provider throws server_error with this message.","triggerScenarios":"Calling the token endpoint with grant_type=token_exchange when the authorization server's OAuth2TokenGenerator cannot emit a token for the requested context — typically because neither a JwtGenerator nor an OAuth2AccessTokenGenerator matches the context (e.g. no JwtEncoder configured and token format not opaque-eligible).","commonSituations":"Security config missing a NimbusJwtEncoder bean on OAuth2AuthorizationServerConfigurer's tokenGenerator; token exchange enabled but the default token settings (e.g. reference vs self-contained) yield no matching generator; authorization-server metadata/customizer restricting the access-token format.","solutions":["Configure a token generator that supports the context: set oauth2AuthorizationServerConfigurer.tokenGenerator(...) with a JwtGenerator and/or OAuth2AccessTokenGenerator","Register a NimbusJwtEncoder (JWKSource-based) bean so JwtGenerator can produce self-contained access tokens","Check the registered authorization's token settings (accessTokenFormat) match an available generator (JWT vs opaque/REFERENCE_TOKEN)","Enable trace logging to inspect the OAuth2TokenContext and confirm which generator is expected"],"exampleFix":"// before: no generator for JWT\nOAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);\n// after\nNimbusJwtEncoder jwtEncoder = new NimbusJwtEncoder(jwkSource);\nJwtGenerator jwtGenerator = new JwtGenerator(jwtEncoder);\njwtGenerator.setJwtCustomizer(...);\nhttp.getConfigurer(OAuth2AuthorizationServerConfigurer.class)\n    .tokenGenerator(jwtGenerator)\n    .tokenGenerator(new OAuth2AccessTokenGenerator());","handlingStrategy":"validation","validationCode":"// startup check: ensure a generator exists for the configured token format\nOAuth2TokenContext ctx = new OAuth2TokenContext() {} // build sample access-token context\nif (tokenGenerator.generate(tokenContext) == null) {\n  throw new IllegalStateException(\"No OAuth2TokenGenerator configured for the access token format\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  return tokenEndpoint.exchange(request);\n} catch (OAuth2AuthenticationException e) {\n  if (\"server_error\".equals(e.getError().getErrorCode())) {\n    log.error(\"Token generation failed — check JwtEncoder/tokenGenerator configuration\", e);\n  }\n  throw e;\n}","preventionTips":["Always register JwtGenerator and/or OAuth2AccessTokenGenerator with OAuth2AuthorizationServerConfigurer.tokenGenerator(...)","Provide a NimbusJwtEncoder backed by a JWKSource for self-contained tokens","Match accessTokenFormat in token settings to an available generator","Re-run authorization-server config tests after upgrading Spring Security versions"],"tags":["oauth2","token-exchange","token-generator","configuration"],"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"}