JWT vs Sessions vs OAuth — When to Use Which Auth Strategy
Cookies and session IDs vs. JWT tokens vs. OAuth providers. Trade-offs, security pitfalls, and how to pick the right one for your stack.
Three authentication patterns dominate modern web apps: session cookies, JWTs, and OAuth. They're often discussed as competitors but they actually solve different problems. Pick the wrong one and you'll spend the next two years working around its tradeoffs. Pick the right one and authentication mostly disappears as a concern.
Inspect any JWT: the JWT Decoder decodes header, payload and signature with auto-expiry check. 100% client-side — never paste production tokens into other sites.
Session cookies — the classic
The pattern that powered the web for 20+ years:
- User logs in. Server creates a record in its session store (Redis, database, memcache).
- Server returns a session cookie containing only an opaque ID (e.g.
sess=abc123…). - On each subsequent request, server looks up the session ID and retrieves user state.
The session ID itself contains no user data. Everything lives in your server-side store.
JWTs (JSON Web Tokens)
JWTs invert the model: the token itself contains the user data, cryptographically signed by the server.
- User logs in. Server creates a JSON payload (
{ "userId": 42, "role": "admin", "exp": 1779036600 }) and signs it. - Server returns the JWT.
- On each request, server verifies the signature and trusts the contents — no database lookup needed.
A JWT looks like three Base64-encoded segments: eyJhbGc…header.eyJzdWI…payload.fLZbi…signature.
OAuth
OAuth isn't a competitor to the above — it's a protocol for delegating authenticationto another service. "Sign in with Google" is OAuth. The flow:
- Your app redirects user to Google.
- User logs into Google (or is already logged in).
- Google asks "Allow this app to know your email?"
- Google redirects back to your app with an authorisation code.
- Your app exchanges the code for an access token (often a JWT, sometimes an opaque token).
- Your app uses the access token to call Google APIs or just gets the user's profile.
OAuth typically issues JWTs OR session-style tokens — so it's a layer above the JWT vs session question.
Sessions vs JWTs — the real tradeoffs
Sessions: stateful, revocable, simpler
Pros:
- Revocation is trivial. Delete the session record — that user is logged out.
- Small cookies. Just an ID, no payload.
- Mature ecosystem. Every framework has battle-tested session middleware.
- Easy to add new data. Server-side state can grow without bumping cookie size.
Cons:
- Requires server-side storage. Adds infrastructure (Redis, DB).
- Sticky session or shared storage required in multi-server deployments.
- Database lookup per request. A small but real cost at scale.
JWTs: stateless, scalable, harder to revoke
Pros:
- No server-side lookup. Verify the signature, trust the payload. Scales horizontally.
- Works across services. One service signs; many services verify. Useful for microservices.
- Self-contained. No external infrastructure needed for auth state.
- Cross-domain friendly. Pass the token; works anywhere.
Cons:
- Revocation is hard. A JWT remains valid until its expiry — you can't "log a user out" without infrastructure to track invalidated tokens (deny lists, version numbers).
- Bigger requests. Token contains payload, so every request carries hundreds of bytes more than a session cookie.
- Stale data. If user role changes, the JWT still says the old role until expiry.
- Lots of footguns. Algorithm confusion attacks (
alg: none), key disclosure, signature validation bypasses — JWTs have a long history of implementation bugs.
When to use sessions
- Most web apps with a database. Sessions are easier and more secure for typical CRUD apps.
- Anything that needs reliable "log this user out". Banking, sensitive data, anywhere account hijacking matters.
- Single-domain apps. Cookies just work.
- Small to medium scale. Up to ~100k req/sec, the session store cost is negligible.
When to use JWTs
- Microservices. Token issued by auth service, verified by everyone.
- Mobile/native apps talking to multiple APIs. Token in header is portable.
- Public-facing APIs with rate limiting per token.
- Short-lived authorisation (5-15 minute access tokens that you refresh).
- Cross-domain scenarios where cookies are awkward.
The hybrid pattern (what most apps actually use in 2026)
- Short-lived JWT access tokens (15 minutes), kept in memory or short-lived cookie.
- Long-lived refresh tokens (often opaque, stored server-side), used to get new access tokens.
- Logout = invalidate refresh token in the database. Existing access tokens expire in <15 minutes anyway.
This gives you JWT scalability AND practical revocation. It's the model used by Auth0, AWS Cognito, Firebase, Supabase and most production auth systems.
OAuth — when you need it
- "Sign in with Google/Apple/GitHub" — you offload authentication entirely.
- Your app needs to call third-party APIs on behalf of the user (e.g. read their Google Calendar).
- You're building a B2B product where companies want SSO with their existing identity provider (Okta, Azure AD).
OAuth is complex to implement from scratch. Use a library (NextAuth, Auth0, Clerk) — don't roll your own.
JWT security mistakes that cost real money
- Trusting
algfrom the token header. An attacker can sendalg: noneif your verification doesn't enforce the algorithm. Always pin the expected algorithm in your verification code. - Storing JWTs in localStorage. Vulnerable to XSS. Use HTTP-only cookies for sensitive use cases.
- Including secrets in the payload. JWTs are NOT encrypted by default — anyone can read the payload. The signature only verifies it wasn't tampered with.
- Forgetting expiry. Tokens without
expare valid forever. Always set it. - Long expiry windows. 24-hour JWTs without refresh tokens = 24-hour breach window when stolen.
The decision flow
- Building a single-domain web app with a database? Sessions.
- Microservices or multiple APIs? JWTs with short expiry + refresh tokens.
- Mobile app calling your API? JWTs with short expiry + refresh tokens.
- Need "sign in with Google"? OAuth + whatever the OAuth provider returns (usually JWTs).
- Enterprise SSO? OAuth/OIDC with an identity provider.
Inspect tokens safely: JWT Decoder — 100% in-browser. Header, payload, expiry, validity status. Never paste production tokens into public services.