-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Describe the bug
OAuth2AuthorizationCodeAuthenticationProvider does not respect the generated OAuth2AccessToken.TokenType and set it always to Bearer.
The internal class method OAuth2AuthenticationProviderUtils.accessToken.accessToken used by OAuth2AuthorizationCodeAuthenticationProvider do not respect the TokenType generated by the OAuth2TokenGenerator even if this is creating an OAuth2AccessToken that contains a TokenType
Access token token_type field should be able to store custom values per spec:
- https://datatracker.ietf.org/doc/html/rfc6749#section-5.1
- https://datatracker.ietf.org/doc/html/rfc6749#section-7.1
To Reproduce
Create a custom generator that returns an OAuth2AccessToken with a custom TokenType
public class CustomGenerator implements OAuth2TokenGenerator<OAuth2AccessToken> {
public CustomGenerator() {
}
@Override
public OAuth2AccessToken generate(OAuth2TokenContext context) {
if (!OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType())) {
return null;
}
OAuth2AccessToken.TokenType tokenType = new OAuth2AccessToken.TokenType("custom-type");
String tokenValue = "TEST"
Instant issuedAt = Instant.now();
Instant expiresAt = issuedAt.plus(1, HOUR);
// Return JWT as OAuth2AccessToken with configured token type
return new OAuth2AccessToken(
tokenType,
tokenValue,
issuedAt,
expiresAt
);
}
}Setup the authorization server filter chain with the custom token generator
@Bean
@Order(1)
public SecurityFilterChain authorizationServerSecurityFilterChain(
HttpSecurity http,
) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
OAuth2AuthorizationServerConfigurer.authorizationServer();
var tokenGenerator = new CustomGenerator();
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.tokenGenerator(tokenGenerator) // Configure custom token generator
)
.authorizeHttpRequests((authorize) ->
authorize.anyRequest().authenticated()
)
.exceptionHandling((exceptions) -> exceptions
.defaultAuthenticationEntryPointFor(
new LoginUrlAuthenticationEntryPoint("/login"),
new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
)
);
return http.build();
}Define the default security chain with login
@Bean
@Order(2)
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http)
throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().authenticated()
)
// Form login handles the redirect to the login page from the
// authorization server filter chain
.formLogin(Customizer.withDefaults());
return http.build();
}Expected behavior
The token sent to the caller and saved to the OAuth2AuthorizationService contains the custom TokenType
Sample