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

 


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:

  1. What OAuth really is
  2. Difference between OAuth and OIDC
  3. How Spring Boot implements OAuth login
  4. Why Spring OAuth becomes stateful by default
  5. How to convert OAuth into a fully stateless system
  6. 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:

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

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

  1. Stores tokens in session
  2. Creates JSESSIONID
  3. Authenticates user using session
  4. 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:

  1. Return ID_TOKEN in response
  2. Do NOT create session
  3. Client stores token
  4. Client sends token every request
  5. 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.

Leave a Reply