spring-bootspring-securityopenid-connectaccess-token

How to use the Spring OAuth2 client to retrieve an access token only?


I've been trying to figure out how to use spring-boot-starter-oauth2-client package to retrieve an oAuth token from an OpenID server.

I can configure the application.yml file with the appropriate settings, and see that the ReactiveClientRegistrationRepository and ServerOAuth2AuthorizedClientRepository beans are created properly.

I'm even able to create a ClientManager, although not entirely sure why this isn't done automatically by SpringBoot. But then, frankly, I am stumped as to how to get an OAuth2Client from the manager.

  security:
    oauth2:
      client:
        registration:
          auth0:
            client-id: MgqYHnr4p3wed9qKdzRu9G
            client-secret: some_secret_code
        provider:
          auth0:
            issuer-uri: https://dev-5cjo8.eu.auth0.com/
    @Bean
    public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(final ReactiveClientRegistrationRepository clientRegistrationRepository,
                                                                         final ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {
        ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
                .clientCredentials()
                .build();

        DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientRepository);

        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
        return authorizedClientManager;
    }

I'm a bit perplexed as to what the next step would be. I am looking to use grant_type: client_credentials and exchange the clientId/secret that are in the application.yml file for an AccessToken, but not sure how to accomplish this.

It would be fairly straightforward to send a request to the token_endpoint using a RestTemplate and parsing the response, but I figure there must be a way to accomplish this using the OAuth2 lib.

How do I use the clientManager to get a client to authenticate using the token endpoint? Keep in mind that I am not looking to build a web-app, or retrieve a specific resource - I am just looking for the access token.


Solution

  • Countless hours of investigating later, I discovered that the DefaultReactiveOAuth2AuthorizedClientManager is intended to be used within a request context. (see https://github.com/spring-projects/spring-security/issues/8444#issuecomment-621567261)

    Accordingly, modifying the ClientManager bean to be defined as:

        @Bean
        public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(final ReactiveClientRegistrationRepository clientRegistrationRepository,
                                                                             final ReactiveOAuth2AuthorizedClientService clientService) {
            ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
                    .clientCredentials()
                    .build();
    
            AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager = new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(clientRegistrationRepository, clientService);
    
            authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
            return authorizedClientManager;
        }
    

    allows for use of the client as follows:

        public String getAccessToken(ReactiveOAuth2AuthorizedClientManager manager){
            OAuth2AuthorizeRequest req = OAuth2AuthorizeRequest.withClientRegistrationId("auth0").principal("N/A").build();
            OAuth2AuthorizedClient client = manager.authorize(req).block();
            return client.getAccessToken().getTokenValue();
        }