Spring Security OAuth Login with WebFlux

1. Overview

Spring Security added OAuth support for WebFlux starting with the 5.1.x GA.

We’ll discuss how to configure our WebFlux application to use OAuth2 Login support. We’ll also discuss how to use WebClient to access OAuth2 secured resources.

The OAuth Login configuration for Webflux is similar to the one for a standard Web MVC application. For more detail on this, also have a look at our article on Spring OAuth2Login element.

2. Maven Configuration

To begin with, we’ll create a simple Spring Boot application and add these dependencies to our pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-client</artifactId>
</dependency>

The spring-boot-starter-securityspring-boot-starter-webflux and spring-security-oauth2-client dependencies are available on Maven Central.

3. Main Controller

Next, we’ll add a simple controller to display the username on the home page:

@RestController
public class MainController {
    
    @GetMapping("/")
    public Mono<String> index(@AuthenticationPrincipal Mono<OAuth2User> oauth2User) {
       return oauth2User
        .map(OAuth2User::getName)
        .map(name -> String.format("Hi, %s", name));
    }
}

Note that we’ll display the username obtained from OAuth2 client UserInfo endpoint.

4. Login Using Google

Now, we’ll configure our application to support login using Google.

First, we need to create a new project at Google Developer Console

Now, we need to add OAuth2 credentials (Create Credentials > OAuth Client ID).

Next, we’ll add this to “Authorized Redirect URIs”:

http://localhost:8080/login/oauth2/code/google

Then, we need to configure our application.yml to use the Client ID and Secret:

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: YOUR_APP_CLIENT_ID
            client-secret: YOUR_APP_CLIENT_SECRET

As we have spring-security-oauth2-client in our path, our application will be secured.

Users will be redirected to log in using Google before they can access our home page.

5. Login Using Auth Provider

We can also configure our application to log in from a custom authorization server.

In the following example, we’ll use our authorization server from a previous article.

This time, we need to configure more properties, not just the ClientID and Client Secret:

spring:
  security:
    oauth2:
      client:
        registration:
          custom:
            client-id: fooClientIdPassword
            client-secret: secret
            scopes: read,foo
            authorization-grant-type: authorization_code
            redirect-uri-template: http://localhost:8080/login/oauth2/code/custom
        provider:
          custom:
            authorization-uri: http://localhost:8081/spring-security-oauth-server/oauth/authorize
            token-uri: http://localhost:8081/spring-security-oauth-server/oauth/token
            user-info-uri: http://localhost:8088/spring-security-oauth-resource/users/extra
            user-name-attribute: user_name

In this case, we also need to specify the scope, grant type and redirect URI for the OAuth2 client. We’ll also provide the authorization and token URI of the Authorization Server.

Finally, we need to configure the UserInfo endpoint as well to be able to get the user authentication details.

6. Security Configuration

By default, Spring Security secures all paths. Therefore, if we have only one OAuth client, we’ll be redirected to authorize this client and log in.

If multiple OAuth clients are registered, then a login page will be automatically created to choose the login method.

We can change that if we like and provide a detailed security configuration:

@EnableWebFluxSecurity
public class SecurityConfig {

    @Bean
    public SecurityWebFilterChain configure(ServerHttpSecurity http) throws Exception {
        return http.authorizeExchange()
          .pathMatchers("/about").permitAll()
          .anyExchange().authenticated()
          .and().oauth2Login()
          .and().build();
    }
}

In this example, we’ve secured all paths except for “/about”.

7. WebClient

We can also do more than just authenticate users using OAuth2. We can use WebClient to access OAuth2 secured resources using OAuth2AuthorizedClient.

Now, let’s configure our WebClient:

@Bean
public WebClient webClient(ReactiveClientRegistrationRepository clientRegistrationRepo, 
  ServerOAuth2AuthorizedClientRepository authorizedClientRepo) {
    ServerOAuth2AuthorizedClientExchangeFilterFunction filter = 
      new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrationRepo, authorizedClientRepo);
    
    return WebClient.builder().filter(filter).build();
}

Then, we can retrieve an OAuth2 secured resource:

@Autowired
private WebClient webClient;

@GetMapping("/foos/{id}")
public Mono<Foo> getFooResource(@RegisteredOAuth2AuthorizedClient("custom") 
  OAuth2AuthorizedClient client, @PathVariable final long id){
    return webClient
      .get()
      .uri("http://localhost:8088/spring-security-oauth-resource/foos/{id}", id)
      .attributes(oauth2AuthorizedClient(client))
      .retrieve()
      .bodyToMono(Foo.class); 
}

Note that we retrieved the remote resource Foo using AccessToken from OAuth2AuthorizedClient.

8. Conclusion

In this quick article, we learned how to configure our WebFlux application to use OAuth2 Login support and how to use WebClient to access OAuth2 secured resources.

As always, the full source code is available over on GitHub.

Related posts:

Java Program to Perform Postorder Recursive Traversal of a Given Binary Tree
Java Program to Check for balanced parenthesis by using Stacks
Removing all Nulls from a List in Java
Java Program to Implement Heap’s Algorithm for Permutation of N Numbers
Tìm hiểu cơ chế Lazy Evaluation của Stream trong Java 8
Extract network card address
Check If a File or Directory Exists in Java
Java Program to Create a Balanced Binary Tree of the Incoming Data
Sắp xếp trong Java 8
Java Program to Implement Caesar Cypher
Java Program to Solve Knapsack Problem Using Dynamic Programming
Java Program to Perform integer Partition for a Specific Case
Java Program to Check if it is a Sparse Matrix
Java Program to Find Strongly Connected Components in Graphs
Mockito and JUnit 5 – Using ExtendWith
Java Program to Implement Miller Rabin Primality Test Algorithm
A Guide to TreeMap in Java
Show Hibernate/JPA SQL Statements from Spring Boot
Java Program to Implement ScapeGoat Tree
Java Program to Implement the Program Used in grep/egrep/fgrep
Creating a Custom Starter with Spring Boot
Predicate trong Java 8
Java Program to Use the Bellman-Ford Algorithm to Find the Shortest Path
Use Liquibase to Safely Evolve Your Database Schema
Java Program to Find Nearest Neighbor for Dynamic Data Set
Spring Boot - Admin Server
Java Program to Implement Bit Array
Java Program to Implement Repeated Squaring Algorithm
Java Program to Perform Sorting Using B-Tree
Using Spring ResponseEntity to Manipulate the HTTP Response
Java Program to Perform String Matching Using String Library
Java Program to Find the Minimum Element of a Rotated Sorted Array using Binary Search approach