How to remove OAuth2AuthorizationCodeAuthenticationConverter for token endpoint in Spring Authorization Server?

48 views Asked by At

I'm trying to use Spring Authorization Server - let's call it 'SAS' (based on Spring Boot 3.1.5) as a fake authorization server that would be used instead of real authorization server that our application uses - for integration tests or Selenium tests - so the test environment doesn't have to have access to the real authorization server.

I can configure the client app to make a direct request to SAS to /oauth2/token endpoint and I would like SAS to return an access token - so the client sends its clientId and clientSecret - and SAS returns a token.

The problem: the POST request from the client doesn't have the "code" attribute. Because of that the request in rejected by SAS in OAuth2AuthorizationCodeAuthenticationConverter.convert() in lines:

Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();
MultiValueMap<String, String> parameters = OAuth2EndpointUtils.getParameters(request);
String code = (String)parameters.getFirst("code");
if (!StringUtils.hasText(code) || ((List)parameters.get("code")).size() != 1) {
                OAuth2EndpointUtils.throwError("invalid_request", "code", 
"https://datatracker.ietf.org/doc/html/rfc6749#section-5.2");
            }

My server configuration:

@Bean
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);

        var authorizationServerConfigurer = http.getConfigurer(OAuth2AuthorizationServerConfigurer.class);
        authorizationServerConfigurer.oidc(Customizer.withDefaults());

        authorizationServerConfigurer.tokenEndpoint(tokenEndpoint ->
                tokenEndpoint
                        .accessTokenRequestConverters(new AuthenticationConverterConsumer())
                        .accessTokenRequestConverter(
                          new CustomOAuth2AuthorizationCodeAuthenticationConverter())
        );

        return http.build();
    }

I can add my own CustomOAuth2AuthorizationCodeAuthenticationConverter (I'm intentionally omitting AuthenticationConverterConsumer details which is irrelevant here) to the existing list of default converters but I don't know if it is possible to also remove the OAuth2AuthorizationCodeAuthenticationConverter so the token request is not rejected by this class.

During SAS startup the OAuth2TokenEndpointConfigurer.configure() is called which calls

OAuth2TokenEndpointFilter tokenEndpointFilter = new OAuth2TokenEndpointFilter(authenticationManager, authorizationServerSettings.getTokenEndpoint());
List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters();
if (!this.accessTokenRequestConverters.isEmpty()) {
            authenticationConverters.addAll(0, this.accessTokenRequestConverters);
}

and OAuth2TokenEndpointFilter constructor simply calls

this.authenticationConverter = new DelegatingAuthenticationConverter(Arrays.asList(
    new OAuth2AuthorizationCodeAuthenticationConverter(), 
    new OAuth2RefreshTokenAuthenticationConverter(), 
    new OAuth2ClientCredentialsAuthenticationConverter(), 
    new OAuth2DeviceCodeAuthenticationConverter()));

so the list of converters in hardcoded and includes OAuth2AuthorizationCodeAuthenticationConverter.

Question: is it possible to configure tokenEndpoint so it doesn't use OAuth2AuthorizationCodeAuthenticationConverter ?

P.S. I know that what I'm trying to do is probably against OAuth2 specification. I just need to know if it is somehow possible to tweak the SAS to allow it.

Thank you in advance for any hints.

I also tried with AuthenticationConverterConsumer whit the following implementation:

public class AuthenticationConverterConsumer implements Consumer<List<AuthenticationConverter>> {
    List<AuthenticationConverter> converters = new ArrayList<>(10);
    @Override
    public void accept(List<AuthenticationConverter> authenticationConverters) {
        /*
        0 = {CustomOAuth2AuthorizationCodeAuthenticationConverter@7242}
        1 = {OAuth2AuthorizationCodeAuthenticationConverter@7237}
        2 = {OAuth2RefreshTokenAuthenticationConverter@7243}
        3 = {OAuth2ClientCredentialsAuthenticationConverter@7244}
        4 = {OAuth2DeviceCodeAuthenticationConverter@7245}
         */

        Iterator<AuthenticationConverter> iterator = authenticationConverters.iterator();
        while(iterator.hasNext()) {
            AuthenticationConverter converter = iterator.next();
            if(converter instanceof OAuth2AuthorizationCodeAuthenticationConverter) {
                iterator.remove();
            }
        }

        converters.addAll(authenticationConverters);
    }
}

but the OAuth2AuthorizationCodeAuthenticationConverter is still available and rejects the requests because of the missing "code" attribute.

0

There are 0 answers