OAuth 2.0 vs OIDC – Complete Guide with Stateless Spring Boot Implementation

OAuth is one of the most misunderstood topics in security.
Most developers use it daily (Google login, GitHub login) but don’t truly understand what is happening internally.
This article explains:
- What OAuth really is
- Difference between OAuth and OIDC
- How Spring Boot implements OAuth login
- Why Spring OAuth becomes stateful by default
- How to convert OAuth into a fully stateless system
- Real-world implementation strategy
What is OAuth?
OAuth stands for Open Authorization.
OAuth is NOT authentication.
OAuth is an authorization framework that allows:
Secure third-party access to user protected data without sharing passwords.
Example:
- A calendar app accessing your Google Calendar
- A job portal accessing your LinkedIn profile
You never give your password to those apps.
OAuth Grant Types
OAuth provides multiple flows depending on use case:
| Grant Type | Used For |
|---|---|
| Authorization Code | Web apps (most secure) |
| Implicit | Old SPAs (deprecated) |
| Client Credentials | Microservices |
| Password (ROPC) | Trusted internal apps |
| Refresh Token | Renew access |
OAuth vs OIDC (Most Important Concept)
| Feature | OAuth2 | OIDC |
|---|---|---|
| Full form | Open Authorization | OpenID Connect |
| Purpose | Authorization | Authentication |
| Used for | Accessing resources | Verifying user identity |
| Token | Access Token | ID Token + Access Token |
| Token format | Opaque or JWT | Always JWT |
| Scope | read, write, email | openid (mandatory) |
Key Difference in One Line
OAuth answers: “Can this app access data?”
OIDC answers: “Who is this user?”
ID Token (OIDC)
OIDC introduces ID_TOKEN, which is always a JWT.
This token:
- Authenticates the user
- Contains minimal user identity info
- Meant for the client app
Example payload:
{
"sub": "123",
"name": "Nimai",
"email": "nimai@gmail.com"
}
Authorization Code Flow (Recap)
This is the industry standard flow used by:
- GitHub
- Auth0
Step 1 – App Registration
Your app registers with Auth Server.
Example:
- Auth0
- GitLab
- Keycloak
Receives:
client_id
client_secret
Step 2 – Redirect User
User is redirected to:
/authorize
Step 3 – User Login & Consent
User logs in at:
- Auth0
- GitLab
And gives consent.
Step 4 – Authorization Code
Auth server redirects:
/callback?code=XYZ
Step 5 – Exchange Code for Token
Client calls:
POST /token
Receives:
{
"access_token": "...",
"refresh_token": "...",
"id_token": "JWT"
}
Step 6 – Access Resource
Client calls APIs using:
Authorization: Bearer <access_token>
Spring Boot OAuth (Default Behavior)
Spring Boot makes OAuth extremely simple.
You just add:
spring-boot-starter-oauth2-client
And configure:
spring.security.oauth2.client.registration.auth0...
No code required.
What Spring Boot Does Internally
Spring creates:
- Default login page
- Redirect flow
- Token exchange
- User authentication
All handled by:
OAuth2LoginAuthenticationFilter
OidcAuthorizationCodeAuthenticationProvider
The Big Problem: Spring OAuth is STATEFUL
By default Spring:
- Stores tokens in session
- Creates JSESSIONID
- Authenticates user using session
- Never validates token again until session expires
So even if:
- ID_TOKEN expires
- Access token expires
User is still logged in via session.
This breaks true OAuth design.
Why Postman Fails?
When you call API via Postman:
No browser → no cookie → no session
So Spring asks for login again.
Why This is Dangerous
Scenario:
- Token expires
- Session still valid
- User remains authenticated
This is security bug, not feature.
Making OAuth Truly STATELESS
Correct architecture:
- Return ID_TOKEN in response
- Do NOT create session
- Client stores token
- Client sends token every request
- Server validates token every time
How to Make Spring OAuth Stateless
Step 1 – Disable Session
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
Step 2 – Override Success Handler
@Component
public class OAuthSuccessHandler
extends SimpleUrlAuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(
HttpServletRequest req,
HttpServletResponse res,
Authentication auth) {
OidcUser user = (OidcUser) auth.getPrincipal();
String idToken = user.getIdToken().getTokenValue();
res.getWriter().write(idToken);
}
}
Step 3 – Custom Token Validation Filter
public class OidcTokenFilter
extends OncePerRequestFilter {
@Override
protected void doFilterInternal(
HttpServletRequest req,
HttpServletResponse res,
FilterChain chain) {
String token = req.getHeader("Authorization");
// Validate using JWKS endpoint
// Create Authentication object
// Store in SecurityContext
}
}
Step 4 – Validate Token Using JWKS
Auth servers expose:
/.well-known/jwks.json
You validate:
- Signature
- Issuer
- Expiry
- Audience
Final Stateless OAuth Flow
User → Auth Server → ID_TOKEN
Client stores token
Client sends token on every request
Server validates token each time
No sessions
No cookies
No memory
Why This is the Correct Design
Because now:
- Works with Postman
- Works with mobile apps
- Works with microservices
- Works in Kubernetes
- No session replication
- No sticky sessions
- No Redis session store
OAuth vs JWT vs OIDC (Real World)
| Concept | Role |
|---|---|
| OAuth | Authorization framework |
| OIDC | Authentication layer |
| JWT | Token format |
| Spring Security | Implementation |
Together they form:
Modern Cloud Security Stack
Interview Questions
Q1. Why Spring OAuth is stateful by default?
Because it assumes browser-based login.
Q2. How to make OAuth stateless?
Disable session and return ID_TOKEN.
Q3. Should we store tokens in DB?
No. Validate using JWKS.
Q4. Is OAuth alone enough for login?
No. OAuth needs OIDC for authentication.
Q5. Where is user identity stored?
Inside ID_TOKEN (JWT).
Final Summary for javadoor.com
OAuth is:
✔ Industry standard
✔ Used by Google, GitHub, Facebook
✔ Secure third-party access
✔ No password sharing
But Spring default OAuth:
❌ Uses session
❌ Breaks stateless design
❌ Not cloud native
Correct implementation:
OAuth + OIDC + JWT + Stateless Spring Security
This is the exact architecture used in real companies:
- Netflix
- Uber
- Amazon
- Google APIs
If you understand this flow, you already know enterprise-grade security architecture.