If you're working on a Spring Security (and especially an OAuth) implementation, definitely have a look at the Learn Spring Security course:
>> LEARN SPRING SECURITYMocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.
Get started with mocking and improve your application tests using our Mockito guide:
Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.
Get started with understanding multi-threaded applications with our Java Concurrency guide:
Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:
Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.
But these can also be overused and fall into some common pitfalls.
To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:
Get started with Spring and Spring Boot, through the Learn Spring course:
>> LEARN SPRINGExplore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:
Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.
I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.
You can explore the course here:
Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.
Get started with Spring Data JPA through the guided reference course:
Refactor Java code safely β and automatically β with OpenRewrite.
Refactoring big codebases by hand is slow, risky, and easy to put off. Thatβs where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.
Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions β one for newcomers and one for experienced users. Youβll see how recipes work, how to apply them across projects, and how to modernize code with confidence.
Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.
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-security, spring-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(auth -> auth
.pathMatchers("/about").permitAll()
.anyExchange().authenticated())
.oauth2Login(Customizer.withDefaults())
.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.
