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
| Term | Meaning |
|---|---|
| Resource owner | The user who owns the account |
| Client | Your Spring Boot application |
| Authorization server | The provider that verifies the user, such as Google |
| Client ID and secret | Credentials that identify your application to the provider |
| Redirect URI | The address where the provider sends the user back |
| Scope | The kind of user data your application requests |
| Access token | A 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/googleThe 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,emailSpring 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:emailAdding a second block adds a second button to the login page.
OAuth2 Client and Resource Server
| Role | Starter | Purpose |
|---|---|---|
| Client (login) | spring-boot-starter-oauth2-client | Lets users sign in through a provider |
| Resource server | spring-boot-starter-oauth2-resource-server | Protects 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.
