OAuth2 Login with Google and GitHub in Spring Boot
Learn how to implement OAuth2 Login in Spring Boot using Google and GitHub. Understand OAuth2 flow, client registration, redirect URI, Spring Security configuration, user profile extraction, and production best practices.
Introduction
OAuth2 Login allows users to sign in using external identity providers like:
- GitHub
- Okta
- Azure AD
- Cognito
Instead of building username/password login from scratch, your application delegates authentication to a trusted provider.
Example:
User clicks "Login with Google"
↓
Google authenticates user
↓
Spring Boot receives user profile
↓
Application creates local session/user record
Spring Security provides built-in OAuth2 Login support through spring-boot-starter-oauth2-client. Spring Security’s OAuth2 login uses redirect URIs like /login/oauth2/code/{registrationId} by default, for example /login/oauth2/code/google.
1. What Problem Does OAuth2 Login Solve?
Traditional login requires your application to manage:
- User registration
- Password hashing
- Password reset
- Login security
- MFA
- Account verification
- Credential storage
OAuth2 Login reduces this burden.
flowchart TB
Traditional["Traditional Login"]
--> Passwords["Store Passwords"]
--> Hashing["Hash Passwords"]
--> Reset["Password Reset"]
--> Risk["Credential Risk"]
OAuth2["OAuth2 Login"]
--> Provider["Google / GitHub"]
--> Profile["Receive User Profile"]
--> AppSession["Create App Session"]
2. Real-World Example
Imagine CodeWithVenu allows developers to sign in.
Instead of asking users to create a new password, allow:
Login with Google
Login with GitHub
This is useful for:
- Developer platforms
- SaaS applications
- Learning platforms
- Internal portals
- Admin dashboards
- Community websites
3. OAuth2 Login Flow
sequenceDiagram
participant User
participant SpringBoot
participant Provider as Google/GitHub
participant App
User->>SpringBoot: Click Login with Google/GitHub
SpringBoot->>Provider: Redirect to Authorization URL
Provider->>User: Show login/consent screen
User->>Provider: Approve access
Provider->>SpringBoot: Redirect back with authorization code
SpringBoot->>Provider: Exchange code for token
Provider-->>SpringBoot: Access token + user info
SpringBoot->>App: Create authenticated session
App-->>User: Login success
4. Important OAuth2 Terms
| Term | Meaning |
|---|---|
| Client | Your Spring Boot application |
| Provider | Google or GitHub |
| Client ID | Public identifier of your app |
| Client Secret | Secret used by backend app |
| Redirect URI | URL provider redirects back to after login |
| Scope | User data your app requests |
| Authorization Code | Temporary code returned after consent |
| Access Token | Token used to call provider APIs |
mindmap
root((OAuth2 Login))
Client
Spring Boot App
Provider
Google
GitHub
Credentials
Client ID
Client Secret
Redirect URI
Scope
Authorization Code
Access Token
5. Redirect URI
Redirect URI is very important.
After Google or GitHub authenticates the user, it redirects the browser back to your application.
Spring Security default format:
http://localhost:8080/login/oauth2/code/{registrationId}
Examples:
Google:
http://localhost:8080/login/oauth2/code/google
GitHub:
http://localhost:8080/login/oauth2/code/github
Google’s OAuth documentation explains that redirect URIs are application endpoints where the OAuth server sends responses after user authentication. GitHub OAuth Apps also require an authorization callback URL.
6. Project Structure
oauth2-login-demo
└── src
└── main
└── java
└── com.codewithvenu.oauth2
├── config
│ └── SecurityConfig.java
├── controller
│ └── HomeController.java
├── service
│ └── OAuth2UserService.java
└── OAuth2LoginDemoApplication.java
7. Maven Dependencies
<dependencies>
<!-- Spring Web for REST endpoints and controller pages -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Security core -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- OAuth2 Client support -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
</dependencies>
Dependency Explanation
spring-boot-starter-web
Used to create controllers and REST endpoints.
spring-boot-starter-security
Adds Spring Security filter chain.
spring-boot-starter-oauth2-client
Adds OAuth2 client and OAuth2 Login support.
8. Create Google OAuth Client
Step-by-Step
- Go to Google Cloud Console
- Create or select a project
- Configure OAuth consent screen
- Create OAuth Client ID
- Choose Web Application
- Add authorized redirect URI:
http://localhost:8080/login/oauth2/code/google
- Copy Client ID
- Copy Client Secret
flowchart TB
A["Google Cloud Console"]
--> B["Create Project"]
--> C["OAuth Consent Screen"]
--> D["Create OAuth Client"]
--> E["Add Redirect URI"]
--> F["Copy Client ID and Secret"]
9. Create GitHub OAuth App
Step-by-Step
- Go to GitHub Developer Settings
- Create OAuth App
- Add Application Name
- Add Homepage URL:
http://localhost:8080
- Add Authorization Callback URL:
http://localhost:8080/login/oauth2/code/github
- Copy Client ID
- Generate and copy Client Secret
flowchart TB
A["GitHub Developer Settings"]
--> B["Create OAuth App"]
--> C["Set Homepage URL"]
--> D["Set Callback URL"]
--> E["Copy Client ID"]
--> F["Generate Client Secret"]
GitHub’s OAuth App documentation notes that OAuth Apps use an Authorization callback URL and OAuth Apps cannot have multiple callback URLs.
10. application.yml
spring:
security:
oauth2:
client:
registration:
google:
client-id: ${GOOGLE_CLIENT_ID}
client-secret: ${GOOGLE_CLIENT_SECRET}
scope:
- openid
- profile
- email
github:
client-id: ${GITHUB_CLIENT_ID}
client-secret: ${GITHUB_CLIENT_SECRET}
scope:
- read:user
- user:email
Explanation
registration
Defines OAuth2 clients.
google
Google registration ID.
github
GitHub registration ID.
client-id
Public application identifier.
client-secret
Secret value for backend authentication.
scope
Defines what user information your app requests.
Do not hardcode client secrets in GitHub.
Use environment variables.
11. Environment Variables
For Mac/Linux:
export GOOGLE_CLIENT_ID="your-google-client-id"
export GOOGLE_CLIENT_SECRET="your-google-client-secret"
export GITHUB_CLIENT_ID="your-github-client-id"
export GITHUB_CLIENT_SECRET="your-github-client-secret"
For Windows PowerShell:
$env:GOOGLE_CLIENT_ID="your-google-client-id"
$env:GOOGLE_CLIENT_SECRET="your-google-client-secret"
$env:GITHUB_CLIENT_ID="your-github-client-id"
$env:GITHUB_CLIENT_SECRET="your-github-client-secret"
12. Spring Security Configuration
package com.codewithvenu.oauth2.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http)
throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/public/**").permitAll()
.anyRequest().authenticated()
)
.oauth2Login(oauth2 -> oauth2
.defaultSuccessUrl("/dashboard", true)
)
.logout(logout -> logout
.logoutSuccessUrl("/")
.permitAll()
);
return http.build();
}
}
Code Explanation
authorizeHttpRequests
Defines which URLs are public and which require login.
requestMatchers("/", "/public/**").permitAll()
Home page and public URLs do not require login.
anyRequest().authenticated()
All other endpoints require authenticated user.
oauth2Login
Enables OAuth2 login.
defaultSuccessUrl("/dashboard", true)
After successful OAuth2 login, user is redirected to /dashboard.
logoutSuccessUrl("/")
After logout, user is redirected to home page.
13. OAuth2 Login Architecture in Spring Security
flowchart TB
Browser["Browser"]
--> SecurityFilterChain["SecurityFilterChain"]
SecurityFilterChain --> OAuth2AuthorizationRequestRedirectFilter["OAuth2 Authorization Redirect Filter"]
OAuth2AuthorizationRequestRedirectFilter --> Provider["Google / GitHub"]
Provider --> OAuth2LoginAuthenticationFilter["OAuth2 Login Authentication Filter"]
OAuth2LoginAuthenticationFilter --> UserInfoEndpoint["UserInfo Endpoint"]
UserInfoEndpoint --> SecurityContext["SecurityContext"]
SecurityContext --> Controller["Controller"]
14. Create HomeController
package com.codewithvenu.oauth2.controller;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
public class HomeController {
@GetMapping("/")
public String home() {
return """
Welcome to CodeWithVenu OAuth2 Login Demo.
Login URLs:
/oauth2/authorization/google
/oauth2/authorization/github
""";
}
@GetMapping("/dashboard")
public Map<String, Object> dashboard(
@AuthenticationPrincipal OAuth2User principal) {
return principal.getAttributes();
}
@GetMapping("/me")
public Map<String, Object> me(
@AuthenticationPrincipal OAuth2User principal) {
return Map.of(
"name", principal.getAttribute("name"),
"email", principal.getAttribute("email"),
"attributes", principal.getAttributes()
);
}
}
Code Explanation
@AuthenticationPrincipal
Injects logged-in OAuth2 user.
OAuth2User
Represents authenticated user returned by provider.
principal.getAttributes()
Returns provider user profile data.
For Google, attributes usually include name, email, picture, and subject.
For GitHub, attributes may include login, id, avatar_url, and name.
15. Login URLs
Spring Security automatically creates OAuth2 authorization URLs.
Google login:
http://localhost:8080/oauth2/authorization/google
GitHub login:
http://localhost:8080/oauth2/authorization/github
flowchart LR
User["User"]
--> GoogleLogin["/oauth2/authorization/google"]
--> Google["Google Login"]
User --> GitHubLogin["/oauth2/authorization/github"]
--> GitHub["GitHub Login"]
16. Test Google Login
Start application:
mvn spring-boot:run
Open browser:
http://localhost:8080/oauth2/authorization/google
Flow:
- Browser redirects to Google
- Login using Google account
- Approve consent
- Google redirects back to Spring Boot
- Application redirects to
/dashboard
17. Test GitHub Login
Open browser:
http://localhost:8080/oauth2/authorization/github
Flow:
- Browser redirects to GitHub
- Login using GitHub account
- Authorize application
- GitHub redirects back to Spring Boot
- Application redirects to
/dashboard
18. OAuth2 User Data Flow
sequenceDiagram
participant User
participant App
participant Provider
participant UserInfo
User->>App: Login with Provider
App->>Provider: Redirect authorization request
Provider-->>App: Authorization code
App->>Provider: Exchange code for token
Provider-->>App: Access token
App->>UserInfo: Request user profile
UserInfo-->>App: User attributes
App-->>User: Dashboard
19. Custom OAuth2 Success Handler
Sometimes you want to run custom logic after login.
Use cases:
- Save user to database
- Create local user account
- Generate JWT
- Redirect to frontend app
- Audit login event
package com.codewithvenu.oauth2.config;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class OAuth2LoginSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication authentication)
throws IOException, ServletException {
OAuth2User oauth2User = (OAuth2User) authentication.getPrincipal();
String name = oauth2User.getAttribute("name");
String email = oauth2User.getAttribute("email");
System.out.println("OAuth2 login success: " + name + " - " + email);
response.sendRedirect("/dashboard");
}
}
Update security config:
.oauth2Login(oauth2 -> oauth2
.successHandler(oAuth2LoginSuccessHandler)
)
20. Saving OAuth2 User to Database
In real applications, after OAuth2 login, store or update the user.
flowchart TB
OAuth2Login["OAuth2 Login Success"]
--> ExtractProfile["Extract Profile"]
--> CheckUser["Check User Exists"]
--> SaveOrUpdate["Save / Update User"]
--> CreateSession["Create App Session"]
Example entity:
@Entity
@Table(name = "oauth_users")
public class OAuthUser {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String provider;
private String providerId;
private String name;
private String email;
private String pictureUrl;
}
Example provider values:
google
github
21. Google vs GitHub User Attributes
| Attribute | GitHub | |
|---|---|---|
| Unique ID | sub | id |
| Name | name | name |
| email may be null | ||
| Picture | picture | avatar_url |
| Username | usually email | login |
GitHub email can be missing depending on user privacy settings and scopes.
So do not assume GitHub always returns email.
22. OAuth2 Login with Frontend App
If your frontend is React/Angular/Next.js, common production flow:
sequenceDiagram
participant Frontend
participant Backend
participant Provider
participant DB
Frontend->>Backend: Start OAuth2 login
Backend->>Provider: Redirect
Provider-->>Backend: Authorization code
Backend->>Provider: Exchange token
Backend->>DB: Save/update user
Backend-->>Frontend: Redirect with app session or JWT
For SPA/mobile apps, many teams generate their own application JWT after successful OAuth2 login.
23. Common Redirect URI Problems
| Problem | Cause |
|---|---|
| redirect_uri_mismatch | URI in provider console does not match Spring Boot callback |
| 404 after provider login | Wrong callback URL |
| Invalid client | Wrong client ID |
| Unauthorized client | OAuth app not configured correctly |
| Missing email | Scope/provider privacy settings |
Correct local redirect URIs:
http://localhost:8080/login/oauth2/code/google
http://localhost:8080/login/oauth2/code/github
24. Production Configuration
For production, use real domain:
spring:
security:
oauth2:
client:
registration:
google:
redirect-uri: "https://api.codewithvenu.com/login/oauth2/code/google"
Also update provider console with:
https://api.codewithvenu.com/login/oauth2/code/google
https://api.codewithvenu.com/login/oauth2/code/github
25. Security Best Practices
- Never commit client secrets to GitHub
- Use environment variables or secrets manager
- Use HTTPS in production
- Validate redirect URIs
- Request minimum scopes
- Do not store provider access tokens unless needed
- Encrypt sensitive tokens if stored
- Log login events, not tokens
- Handle missing email carefully
- Use CSRF protection for browser session apps
- Use short-lived sessions
- Review OAuth consent screen settings
26. Common Mistakes
| Mistake | Problem |
|---|---|
| Hardcoding client secret | Secret leakage |
| Wrong redirect URI | Login failure |
| Requesting too many scopes | User trust issue |
| Assuming GitHub email exists | Null pointer bugs |
| Storing access token in logs | Token leakage |
| No HTTPS | Token interception |
| Mixing session and JWT poorly | Security confusion |
27. Interview Questions
Q1. What is OAuth2 Login?
OAuth2 Login allows users to authenticate using external identity providers such as Google or GitHub.
Q2. What is Client ID?
Client ID identifies your application to the OAuth2 provider.
Q3. What is Client Secret?
Client Secret is a confidential value used by backend applications.
Q4. What is Redirect URI?
Redirect URI is where the provider sends the user after authentication.
Q5. What is Scope?
Scope defines what user data or permissions the application requests.
Q6. What is Authorization Code?
Authorization Code is a temporary code returned by provider and exchanged for tokens.
Q7. What Spring Boot dependency is required?
spring-boot-starter-oauth2-client.
Q8. What is the default Spring Security login URL for Google?
/oauth2/authorization/google.
Q9. What is the default callback URI pattern?
/login/oauth2/code/{registrationId}.
28. Key Takeaways
- OAuth2 Login delegates authentication to trusted providers.
- Spring Security supports OAuth2 Login out of the box.
- Google and GitHub require OAuth client configuration.
- Redirect URI must match provider settings.
- Spring Boot uses
/login/oauth2/code/{registrationId}as callback pattern. - Use environment variables for client secrets.
- OAuth2 user profile can be accessed using
@AuthenticationPrincipal OAuth2User. - In production, save/update user after successful login.
- Use HTTPS and request minimum scopes.
Next Article
➡️ OpenID Connect with Spring Security