Skip to content

OAuth2 Client as Application module

Example of application module, which uses OAuth2 client with client credentials grant flow. Example of such applications are batch applications executing tasks, which needs to access API of other modules or systems.

Application utilizes the Spring Security OAuth2 Client, which supports: * logging-in users in using OAuth 2.0 or OpenID Connect 1.0 * obtaining an access token for application in order to access an API

The application also utilizes the Spring WebClient with the Spring Security extension, which adds capabilities as injection of access tokens into HTTP requests (Authorized WebClient).

  1. First add required dependencies into build.gradle file. Spring Boot provides convenient way with starter:

       implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
    
  2. You need to register OAuth2 client with application. The Auth Server defines client with name/id app-client, so you can use it. This client is configured to support Client Credentials OAuth2 grant which is required by this example. There is spring provider configured, which requires OAuth2 token endpoint URI. Then spring provider is used in client registration config. Add following configuration into application.yaml file:

      spring:                                                                                     
        security:                                                                            
          oauth2:                                                                                 
            client:                                                                               
              registration:                                                                       
                # Required for login                                                              
                app-client:                                                                       
                  provider: spring                                                                
                  client-id: app-client                                                           
                  client-secret: secret                                                           
                  client-authentication-method: client_secret_post                                
                  authorization-grant-type: client_credentials                                    
                  redirect-uri: "http://localhost:8080/login/oauth2/code/app-client"              
                  scope: openid                                                                   
                  client-name: Spring                                                             
              provider:                                                                           
                spring:                                                                           
                  token-uri: http://auth-server:9000/oauth2/token                                 
    
  3. The configuration class WebClientConfiguration is used to define required client components. This lab utilizes WebClient from reactive webflux project. You need to plug-in OAuth2 client, which will automatically authorize with Auth Server. Then it adds required client filter, which includes valid access token in o client request sent to Resource Server. Spring Security includes OAuth2AuthorizedClientManager, which maintains register of defined OAuth2 clients and also authorized clients. This manager is used in filter function added to WebClient. The above is achieved by following configuration:

      @Bean                                                                                                                                                                                                          
      WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {                                                                                                                                  
        ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
          new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);                                                        
        return WebClient.builder()                                                                                                                                                                                  
                .filter(oauth2Client)                                                                                                                                                                               
                .build();                                                                                                                                                                                           
      }                                                                                                                                                                                                             
    
      @Bean                                                                                                                                                                                                          
      OAuth2AuthorizedClientManager authorizedClientManager(ClientRegistrationRepository clientRegistrationRepository,                                                                                              
                                                            OAuth2AuthorizedClientService authorizedClientService) {                                                                                                
    
        OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder                                                                                                             
                .builder()                                                                                                                                                                                          
                .clientCredentials()                                                                                                                                                                                
                .build();                                                                                                                                                                                           
        AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager = 
          new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientService);             
        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);                                                                                                                              
        return authorizedClientManager;                                                                                                                                                                         
      }                                                                                                                                                                                                         
    

    Notice the ServletOAuth2AuthorizedClientExchangeFilterFunction added as filter function into WebClient.

  4. The WebClient is used by the ClientService service invoked by scheduled job. ClientService calls Resource Server via API. You need to add OAuth2 client app-client into WebClient execution sequence via attributes() function:

      public void callHallo() {                                          
          webClient.get()                                                     
                  .uri("http://localhost:8090/api/hello")                      
                  .attributes(clientRegistrationId("app-client"))            
                  .retrieve()                                                 
                  .bodyToMono(String.class)                                   
                  .subscribe(LOG::info);                                     
      }                                                                      
    
  5. Now start application and check console. The Auth Server and Resource Server must be up and running.