OAuth2 Login with Google & Facebook in Spring Boot

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:

  • Google
  • Facebook
  • 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

Post a Comment

0 Comments