Spring Boot OAuth2 Login

Many websites offer a "Sign in with Google" or "Sign in with GitHub" button. The button relies on OAuth2 and OpenID Connect. Users prove their identity to a trusted provider, and the provider tells your application who they are. Your application never sees or stores the user's password.

Spring Boot supports this flow with one starter and a handful of properties.

The Festival Wristband Idea

A music festival runs a central ticket office. Visitors show identification at the office and receive a wristband. Gate staff at each stage never check identification; they trust the wristband because the ticket office issued it. OAuth2 login works the same way. The provider acts as the ticket office, the application acts as a stage gate, and the token acts as the wristband.

 Visitor ---- shows ID ----> Ticket office (Google)
 Visitor <--- wristband ----- Ticket office
 Visitor ---- wristband ---> Stage gate (Your app)  --> entry allowed

Key Terms

TermMeaning
Resource ownerThe user who owns the account
ClientYour Spring Boot application
Authorization serverThe provider that verifies the user, such as Google
Client ID and secretCredentials that identify your application to the provider
Redirect URIThe address where the provider sends the user back
ScopeThe kind of user data your application requests
Access tokenA short-lived key that grants access

The Authorization Code Flow

Spring Security follows the authorization code flow, the safest option for web applications.

 1. User clicks "Sign in with Google"
 2. App redirects the browser to Google
 3. User logs in at Google and approves access
 4. Google redirects back with a one-time code
 5. App sends the code and client secret to Google (server to server)
 6. Google returns tokens and user information
 7. App creates a login session for the user

The one-time code in step 4 is useless without the client secret, which stays on the server.

Registering Your Application

Create an OAuth client in the provider's developer console. Google users open the Google Cloud Console, create credentials of type OAuth client ID, and choose Web application. Enter the redirect address.

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

The console returns a client ID and a client secret. Treat the secret like a password.

Adding the Starter

<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>

Configuring the Provider

spring.security.oauth2.client.registration.google.client-id=${GOOGLE_CLIENT_ID}
spring.security.oauth2.client.registration.google.client-secret=${GOOGLE_CLIENT_SECRET}
spring.security.oauth2.client.registration.google.scope=openid,profile,email

Spring Boot already knows the provider addresses for Google, GitHub, Facebook, and Okta. Only the client ID, secret, and scope need settings. Environment variables keep the secret out of source control.

Enabling Login

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/", "/public/**").permitAll()
                .anyRequest().authenticated())
            .oauth2Login(Customizer.withDefaults());
        return http.build();
    }
}

Visiting a protected page now sends the visitor to an automatic login page that lists the configured providers.

Reading the Logged-in User

@RestController
public class ProfileController {

    @GetMapping("/profile")
    public Map<String, Object> profile(@AuthenticationPrincipal OAuth2User user) {
        return Map.of(
                "name", user.getAttribute("name"),
                "email", user.getAttribute("email"));
    }
}

Providers that support OpenID Connect return an OidcUser object, which adds standard claims such as the subject id and email verification status.

@GetMapping("/me")
public String me(@AuthenticationPrincipal OidcUser user) {
    return user.getFullName() + " " + user.getEmail();
}

Connecting to Your Own Users

Applications usually store their own user record and link it to the provider account. A common approach creates a record on first login.

 Login success
     |
 Find user by provider email
     |
   found --> load roles from database
 not found --> create new user with role USER
     |
 Continue to the application

Several Providers

spring.security.oauth2.client.registration.github.client-id=${GITHUB_CLIENT_ID}
spring.security.oauth2.client.registration.github.client-secret=${GITHUB_CLIENT_SECRET}
spring.security.oauth2.client.registration.github.scope=read:user,user:email

Adding a second block adds a second button to the login page.

OAuth2 Client and Resource Server

RoleStarterPurpose
Client (login)spring-boot-starter-oauth2-clientLets users sign in through a provider
Resource serverspring-boot-starter-oauth2-resource-serverProtects an API by checking incoming tokens

Best Practices

  • Store client secrets in environment variables or a secrets manager.
  • Request only the scopes the application needs.
  • Use HTTPS for redirect addresses in production.
  • Register exact redirect URIs and avoid wildcards.
  • Offer a clear sign-out option and explain what data the application reads.

OAuth2 login saves users from creating another password and saves developers from storing credentials. Trusted providers handle the hard security work, and Spring Boot handles the connection.