Securely authenticate users in your Spring Boot application using OAuth2 with popular identity providers like Google and Facebook. This guide walks you through the complete process with working configurations and best practices.
What is OAuth2?
OAuth2 is an open standard protocol for access delegation, commonly used to grant websites or applications limited access to user information without exposing credentials. It's used by major platforms like:
- GitHub
Unlike traditional login systems, OAuth2 allows users to log in using their existing accounts, improving user experience and reducing password-related risks.
Why Use OAuth2 Login?
Integrating OAuth2 login in your Spring Boot application offers several benefits:
- Seamless user experience – Users can log in with one click
- Reduced password fatigue – No need to create a new password
- Better security – No password storage required
- Easy integration using Spring Security OAuth2 Client
OAuth2 vs JWT vs Session-based Auth
Here's how OAuth2 compares to other common authentication strategies:
Method | Token-based (JWT) | Session-based | OAuth2 (Google/Facebook) |
---|---|---|---|
Authentication | Custom Login | Custom Login | Third-Party (Google, Facebook) |
Token Stored | Client-side JWT | Server Session | Provided by OAuth2 Provider |
Best Use | REST APIs | Web Apps | User-Facing Portals |
Spring Boot OAuth2 Login Dependencies
You can enable OAuth2 login using just one dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
This starter provides the core OAuth2 login functionality, token parsing, and auto-config support for various providers.
application.yml Configuration Example
Add your client credentials and redirect URI in application.yml
:
spring:
security:
oauth2:
client:
registration:
google:
client-id: YOUR_GOOGLE_CLIENT_ID
client-secret: YOUR_GOOGLE_CLIENT_SECRET
scope:
- openid
- profile
- email
facebook:
client-id: YOUR_FACEBOOK_CLIENT_ID
client-secret: YOUR_FACEBOOK_CLIENT_SECRET
scope:
- public_profile
- email
provider:
facebook:
authorization-uri: https://www.facebook.com/v10.0/dialog/oauth
token-uri: https://graph.facebook.com/v10.0/oauth/access_token
user-info-uri: https://graph.facebook.com/me?fields=id,name,email
Ensure the redirect URI is registered in your Google/Facebook developer console:
http://localhost:8080/login/oauth2/code/google
http://localhost:8080/login/oauth2/code/facebook
Customizing OAuth2 Login in Spring Boot
Custom Login Page
Spring Security provides a default login form, but you can override it with your own.
First, create a login page HTML (e.g., src/main/resources/templates/login.html
if using Thymeleaf).
<html>
<body>
<h1>Login With</h1>
<a href="/oauth2/authorization/google">Google Login</a><br>
<a href="/oauth2/authorization/facebook">Facebook Login</a>
</body>
</html>
Then, in your security configuration:
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests()
.requestMatchers("/", "/login").permitAll()
.anyRequest().authenticated()
.and()
.oauth2Login()
.loginPage("/login");
return http.build();
}
Accessing User Info
After a successful login, Spring populates the OAuth2User
object with user info from Google or Facebook.
Example controller to get user details:
@RestController
public class UserController {
@GetMapping("/user")
public Map<String, Object> user(@AuthenticationPrincipal OAuth2User principal) {
return principal.getAttributes();
}
}
The principal.getAttributes()
will return a map with keys like:
email
name
picture
Mapping User Roles
By default, Spring doesn’t assign roles from providers. You can configure a custom OAuth2UserService
to map roles:
@Service
public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User oauth2User = new DefaultOAuth2UserService().loadUser(userRequest);
// Assign ROLE_USER manually or based on attributes
return new DefaultOAuth2User(
Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")),
oauth2User.getAttributes(),
"name");
}
}
Register this in your security config using .userInfoEndpoint().userService(...)
.
Logout Configuration
To allow users to log out and redirect them:
http.logout()
.logoutSuccessUrl("/").permitAll();
Optionally, add a logout button:
<a href="/logout">Logout</a>
Enable CSRF for Web Apps (Optional)
If you’re working with a traditional web app and want CSRF protection:
http
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
Add the token to headers via JavaScript or meta tags for form submissions.
Storing OAuth2 User Info in a Database
Why Store Users in a DB?
After a user logs in using Google or Facebook, it’s useful to save their profile information to your own database. This allows:
- User tracking
- Role or profile customization
- Permission control
Sample User Entity
Create a basic JPA entity to store user details.
@Entity
public class AppUser {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String provider; // google, facebook
private String providerId;
private String name;
private String email;
private String imageUrl;
}
Save on First Login
Extend your CustomOAuth2UserService
to store users if they don't already exist.
@Service
public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
@Autowired
private AppUserRepository userRepository;
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User oauth2User = new DefaultOAuth2UserService().loadUser(userRequest);
String email = oauth2User.getAttribute("email");
String name = oauth2User.getAttribute("name");
Optional<AppUser> userOpt = userRepository.findByEmail(email);
if (!userOpt.isPresent()) {
AppUser newUser = new AppUser();
newUser.setEmail(email);
newUser.setName(name);
newUser.setProvider(userRequest.getClientRegistration().getRegistrationId());
newUser.setProviderId(oauth2User.getName());
userRepository.save(newUser);
}
return oauth2User;
}
}
Common OAuth2 Errors and Fixes
- 403 Forbidden:
/login/oauth2/code/*
path not registered → Check redirect URI - invalid_client: Incorrect client ID/secret → Verify from Google/Facebook console
- Missing scopes: Add required
scope:
entries in your YAML config
Production Configuration Tips
- Always serve OAuth over HTTPS
- Do not expose
client-secret
in frontend - Normalize email and providerID for duplicate detection
- Consider audit logging login activity
- Set account status flags (active, deleted) on user table
0 Comments