Skip to content

OAuth2AuthenticationProviderUtils.accessToken not respecting token_type #2210

@lacebal

Description

@lacebal

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:

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions