Search code examples
springoauth-2.0oauthspring-oauth2

Spring Security OAuth2: DelegatingOAuth2AuthorizedClientProvider provides only one type of provider


I'm developing a client app using Spring Security OAuth 2.0 Client with resource owner password flow. I used this tutorial as a reference, but with password authorization grant type.

spring.security.oauth2.client.registration.keycloak.authorization-grant-type=password

My request looks as follows:

OAuth2AuthorizeRequest oAuth2AuthorizeRequest = OAuth2AuthorizeRequest
                .withClientRegistrationId(clientRegistration.getRegistrationId())
                .attributes(attrs -> {
                    attrs.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, username);
                    attrs.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, password);
                    attrs.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
                })
                .principal(principal)
                .build();

This call results in null client:

OAuth2AuthorizedClient client = manager.authorize(oAuth2AuthorizeRequest);

I'vr debugged the app and found out that List<OAuth2AuthorizedClientProvider> authorizedClientProviders in DelegatingOAuth2AuthorizedClientProvider contains only ClientCredentialsOAuth2AuthorizedClientProvider. So password provider(PasswordOAuth2AuthorizedClientProvider) isn't there and I get null client.

Versions:

  • Spring Boot 2.7.10
  • Spring Security OAuth Client 5.7.7

Any help is welcomed!

Update: Fixed OAuth2AuthorizedClientProvider initialization, but it still looks like there is no support for username/password attributes during context build

OAuth2AuthorizationContext authorizationContext = buildAuthorizationContext(authorizeRequest, principal,
            contextBuilder);

Solution

  • according to the official documentation, you could try something like this:

    @Bean
    public OAuth2AuthorizedClientManager authorizedClientManager(
            ClientRegistrationRepository clientRegistrationRepository,
            OAuth2AuthorizedClientRepository authorizedClientRepository) {
    
        OAuth2AuthorizedClientProvider authorizedClientProvider =
                OAuth2AuthorizedClientProviderBuilder.builder()
                        .authorizationCode()
                        .refreshToken()
                        .clientCredentials()
                        .password() // what is needed for you
                        .build();
    
        DefaultOAuth2AuthorizedClientManager authorizedClientManager =
                new DefaultOAuth2AuthorizedClientManager(
                        clientRegistrationRepository, authorizedClientRepository);
        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
    
        return authorizedClientManager;
    }
    

    for all the detaisl please visit this link