JWT, OAuth2, SSO — I Kept Mixing These Up. Here's the Difference.
N I R A N J A N Developing in Web3 and AI
On this page
The Confusion That Started This
What Authentication Actually Is
Basic Authentication — The Simplest Form
Session-Based Authentication — The Stateful Approach
Bearer Tokens and JWT — The Modern Standard
Access Tokens vs Refresh Tokens
OAuth 2.0 — Not Authentication, Authorization
OpenID Connect — Authentication on Top of OAuth2
SSO — Not a Method, an Experience
The Full Picture
The Takeaway
For the longest time I thought JWT, OAuth2, and SSO were all roughly the same thing — "ways to log in." I'd use them interchangeably in conversation and nobody corrected me, so I never found out how wrong that was.
Then I actually sat down and read through each one properly. Turns out they're not even the same category of thing. One's a token format. One's an authorization framework. One's a user experience pattern. None of them do what I assumed they did.
Here's the breakdown, finally straightened out.
What Authentication Actually Is
Authentication answers one question: who are you?
It's the process of verifying identity — a user logging in through a browser, or a service calling an API. This always happens before authorization, which is a separate question: what are you allowed to do?
If a request shows up without valid credentials or a valid token, the server responds with a 401 Unauthorized. That's the gate. Nobody gets past it without proving who they are first.
Client Request
↓
Authenticated? ──No──→ 401 Unauthorized
↓ Yes
Authorized? ──No──→ 403 Forbidden
↓ Yes
Access Granted
Keep this flow in mind — almost every confusion in this space comes from mixing up the "who are you" step with the "what can you do" step.
Basic Authentication — The Simplest Form
The most barebones approach: send a username and password, Base64-encoded, in the HTTP Authorization header.
Client Server
│ │
├── GET /api/users ───────────────────────→│
│ │
│←──────────── 401 Unauthorized ───────────┤
│ │
├── GET /api/users │
│ + Authorization: Basic base64(u:p) ───→│
│ │ (decode + validate)
│←──────────────── 200 OK ──────────────────┤
The problem: Base64 is encoding, not encryption. It's trivially reversible. Anyone intercepting the request can decode it instantly. Credentials are also sent with every single request — more exposure, more risk.
Basic Auth is rarely used in production unless paired with HTTPS to encrypt the channel itself. Even then, it's mostly a relic at this point.
Session-Based Authentication — The Stateful Approach
A more common traditional approach: log in once, server creates a session, client holds onto a session ID via a cookie.
Client Server Redis/Session Store
│ │ │
├── Login (credentials) →│ │
│ ├── Create session ─────────→│
│ │ │
│←── Set-Cookie: session_id=abc123 ────────────────────┤
│ │ │
├── Request │ │
│ + Cookie: abc123 ───→│ │
│ ├── Look up session ────────→│
│ │←──────── Session valid ─────┤
│←──────────── 200 OK ───┤ │
This is stateful — the server has to remember every active session somewhere, typically Redis for fast lookups and built-in expiration. Works well for traditional web apps but becomes a scaling headache in distributed systems, where every server instance needs access to the same session store.
This is exactly why token-based authentication exists — to remove that stateful dependency.
Bearer Tokens and JWT — The Modern Standard
A bearer token is a pattern, not a specific technology. The name says it all — whoever bears this token gets access. No further verification of identity needed at the point of use.
Authorization: Bearer <token>
The most common format for that token today is the JWT — JSON Web Token. And here's the first big misconception I had: JWT isn't an authentication method. It's a token format — a specific structure for encoding claims.
A JWT has three parts, separated by dots:
JWT, OAuth2, SSO — I Kept Mixing These Up. Here's the Difference.
Updated
May 26, 2026
• 10 min read
N I R A N J A N
Developing in Web3 and AI
┌──────────────────────────────────┐
│ JWT │
└──────────────────────────────────┘
│
┌───────────────────────────┼───────────────────────────┐
↓ ↓ ↓
Header Payload Signature
│ │ │
↓ ↓ ↓
Signing algorithm + User ID, roles, Verifies token
token type claims wasn't tampered
header.payload.signature
The header describes how it's signed. The payload carries the actual claims — user ID, roles, whatever the app needs. The signature proves the token hasn't been altered since it was issued.
The key advantage: JWTs are self-contained. The server can verify a token's validity just by checking its signature — no database query required. That's a huge win for scalability, since you're not hitting a session store on every request anymore.
The tradeoff: since JWTs are valid until they expire, a stolen token is dangerous for its entire lifetime. This is why short expiry times are recommended.
Access Tokens vs Refresh Tokens
Short expiry solves the security problem but creates a usability one — nobody wants to log in again every 15 minutes.
The fix: use two tokens instead of one.
Client Server
│ │
├── Login ───────────────────────────────────────→│
│←── Access Token (15 min) + Refresh Token ────────┤
│ │
├── API request + Access Token ────────────────────→│
│←──────────────── 200 OK ──────────────────────────┤
│ │
│ ... 15 minutes later, access token expired ...
│ │
├── API request + expired Access Token ─────────────→│
│←──────────────── 401 Unauthorized ─────────────────┤
│ │
├── Refresh request + Refresh Token ─────────────────→│
│←──────────────── New Access Token ─────────────────┤
The access token is short-lived — 15 minutes to an hour — and used for actual API calls. The refresh token is long-lived, stored more securely (typically an HTTP-only cookie to prevent XSS attacks), and used only to get a new access token without forcing a full re-login.
This balances security and usability — a stolen access token is only dangerous for a short window, while the user experience stays seamless.
OAuth 2.0 — Not Authentication, Authorization
Here's the misconception that surprised me most: OAuth2 is not an authentication method. It's an authorization framework.
OAuth2 answers a completely different question — not "who are you" but "what is this third-party app allowed to access on your behalf?"
Think about granting an app access to your Google Drive:
User App Google
│ │ │
├── Click "Connect │ │
│ Google Drive" ───→│ │
│ ├── Redirect to consent ────→│
│←──────────────── Request permission ──────────────┤
├── Approve ──────────────────────────────────────→│
│ │←── Authorization Code ──────┤
│ ├── Exchange code for │
│ │ Access Token ────────────→│
│ │←──────── Access Token ───────┤
│ ├── API call with Access Token →│
│ │←──────── Drive files ─────────┤
At no point does OAuth2 tell the app who you are. It only controls what resources the app can touch. That distinction is the whole point — and it's exactly what gets confused constantly, including by me until I actually read the spec properly.
OpenID Connect — Authentication on Top of OAuth2
So if OAuth2 doesn't handle identity, how does "Sign in with Google" actually authenticate you?
That's OpenID Connect (OIDC) — a layer built on top of OAuth2 specifically to add authentication. It introduces a new piece: the ID token, a JWT containing actual identity claims like user ID, email, and profile info.
User App Google
│ │ │
├── Click "Sign in │ │
│ with Google" ────→│ │
│ ├── Redirect to OIDC ───────→│
│←──────────────── Login + consent screen ──────────┤
├── Approve ──────────────────────────────────────→│
│ │←── Authorization Code ──────┤
│ ├── Exchange code ───────────→│
│ │←── Access Token + ID Token ──┤
│ │ (verify ID Token, │
│ │ create session) │
OAuth2 gives you the access token for resource access. OIDC adds the ID token specifically for identity verification. Together, they're why "Sign in with Google" both logs you in and can request access to your Drive or Calendar in the same flow.
SSO — Not a Method, an Experience
The last piece of confusion: Single Sign-On isn't an authentication method at all. It's a user experience pattern — log in once, access multiple related apps without logging in again.
User logs into Identity Provider
│
↓
Shared SSO Session
│
┌───────────────┼───────────────┬──────────────┐
↓ ↓ ↓ ↓
Gmail Google Drive YouTube Any connected app
Underneath SSO, the actual identity verification is handled by protocols like SAML (XML-based, common in enterprise and legacy systems) or OpenID Connect (JSON-based, common in consumer apps). SSO is the experience; SAML or OIDC is the mechanism making it work.
The Full Picture
Here's how all the pieces actually relate to each other — not interchangeable, but layered:
┌─────────────────────────────┐
│ AUTHENTICATION │
│ (answers: "who are you") │
│ │
│ • Basic Auth │
│ • Session-Based │
│ • Bearer Token / JWT ───────┼──┐
└─────────────────────────────┘ │
↓
┌─────────────────────────────┐ ┌─────────────────────────────┐
│ AUTHORIZATION │ │ IDENTITY LAYER │
│ (answers: "what can you │→ │ OpenID Connect │
│ access") │ │ (adds identity on top │
│ OAuth 2.0 ──────────────┼─→│ of OAuth2) │
└─────────────────────────────┘ └─────────────────────────────┘
│
↓
┌─────────────────────────────┐
│ EXPERIENCE │
│ Single Sign-On │
│ (powered by OIDC or SAML) │
└─────────────────────────────┘
Authentication methods — Basic, Digest, API Key, Session, JWT — answer "who are you"
OAuth2 — an authorization framework — answers "what can this app access"
OpenID Connect — builds identity verification on top of OAuth2
SSO — the experience layer, powered underneath by OIDC or SAML
None of these are interchangeable. Each sits at a different layer of the stack, solving a different problem.
The Takeaway
I spent way too long treating these as synonyms. Five things I now actually understand:
JWT is a token format, not a method — header, payload, signature
Bearer token is a pattern — whoever holds it gets access, no further check
OAuth2 is authorization, not authentication — it controls access, not identity
OpenID Connect adds the missing identity layer on top of OAuth2 via the ID token
SSO is a UX pattern, not a protocol — SAML or OIDC does the actual work underneath
Knowing what each technology actually is — and just as importantly, what it isn't — is the difference between using these correctly and quietly building something insecure while thinking you understood it.
Follow me on X @nirxnjxn7 where I build stuff, break stuff, and write about both.
