When you think about security in distributed systems or microservices, you want it to be unified, scalable, and easy to manage. OAuth2 gives you a centralized approach to authentication, letting you delegate authorization to third-party providers (like Google, GitHub). With Spring Security you can get all of this up and running with minimal fuss thanks to its tight integration — we’ll dig into that now.
Key features of OAuth2 with Spring Security
Before we start poking at code, let’s quickly go over what you get from integrating OAuth2 with Spring Security:
- Unified authentication: you don’t have to build your own sign-in and user verification flow. You can use ready-made providers like Google, GitHub, and other popular services.
- Token exchange: OAuth2 lets you obtain access tokens and Refresh tokens that are then used to protect resources.
- Flexible roles and access control: you can easily manage user roles and protect resources based on them.
Configuring Spring Security to work with OAuth2
1. Adding dependencies
First, you need to add the required dependencies to your pom.xml (if you use Maven) or build.gradle (if you use Gradle). For OAuth2 support in Spring Security add these dependencies:
Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Gradle:
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-security'
2. OAuth2 client configuration
Spring Boot already plays nicely with OAuth2 providers like Google and GitHub, so configuration is pretty straightforward. All you need is to add the config to your application.yml:
spring:
security:
oauth2:
client:
registration:
google:
client-id: YOUR_GOOGLE_CLIENT_ID
client-secret: YOUR_GOOGLE_CLIENT_SECRET
scope:
- email
- profile
redirect-uri: "{baseUrl}/login/oauth2/code/google"
client-name: Google
provider:
google:
authorization-uri: https://accounts.google.com/o/oauth2/v2/auth
token-uri: https://oauth2.googleapis.com/token
user-info-uri: https://openidconnect.googleapis.com/v1/userinfo
Don’t forget to replace YOUR_GOOGLE_CLIENT_ID and YOUR_GOOGLE_CLIENT_SECRET with your own values. You can get them by registering your app in the Google Cloud Console.
3. Controller setup
After the config is in place, we need to make sure the user will be redirected to the OAuth2 login page. Spring Security does that for you automatically, but a controller is useful to verify authorization.
Let’s create a simple test controller:
@RestController
public class HelloController {
@GetMapping("/")
public String home(@AuthenticationPrincipal OAuth2User principal) {
String email = principal.getAttribute("email");
return "Hello, " + email + "! You are successfully authenticated.";
}
}
Here we used the @AuthenticationPrincipal annotation to get the current user object from the security context.
How this all works
Here’s the flow when interacting with an OAuth2 provider in practice:
- The user clicks the sign-in button on your site.
- They get redirected to the provider’s authorization page (for example, Google).
- After a successful sign-in the provider returns a token.
- Your app uses the token to access user data (like name or email).
Protecting resources with roles
Say you need to restrict access to some resources to specific roles only. Here’s how you can do it:
1. Add a security filter in your Spring Security configuration
Create a security configuration class:
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/", "/login").permitAll()
.anyRequest().authenticated()
.and()
.oauth2Login(); // Enable OAuth2 for login
}
}
2. Working with user roles
By default Spring Security lets you use custom roles. Make sure your OAuth2 provider supplies them. If not, you can extend functionality with a custom mapper:
@Component
public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User oAuth2User = new DefaultOAuth2UserService().loadUser(userRequest);
// Add the "USER" role to all authenticated users
List<GrantedAuthority> authorities = new ArrayList<>(oAuth2User.getAuthorities());
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new DefaultOAuth2User(authorities, oAuth2User.getAttributes(), "name");
}
}
With this setup you can add your own roles for users, for example based on data received from the OAuth2 provider.
Practical assignment
- Set up a Spring Boot app to authenticate via Google.
- Implement a controller that returns a greeting message with the authenticated user’s email.
- Restrict access to certain URLs to users with the "ADMIN" role only.
FAQs and common mistakes
- I get an "invalid_client" error when signing in with Google. Check that your
client-idandclient-secretare correct. Also make sure the redirect URL matches what’s configured in Google Cloud Console. - OAuth2 ignores the role set in the configuration. Ensure your provider returns roles in its response. If it doesn’t, use a custom
OAuth2UserService. - The token expires too quickly. That may be due to the provider’s token lifetime settings. Consider using Refresh tokens to renew access.
That’s it for this lecture. You learned how to set up OAuth2 in Spring Security, authenticate users via third-party services (Google, GitHub), and protect resources using roles. In the next lectures we’ll dive deeper into working with JWT, Refresh tokens, and configuring microservices. See you!
GO TO FULL VERSION