Skip to content
Back to blog
AuthenticationJWTOAuthSecurityAPI

JWT vs Session vs OAuth 2.0

July 4, 202610 min read

Authentication in modern apps spans three distinct models. Sessions store user state on the server and send a session ID in a cookie — simple and revocable, but requiring sticky sessions or a shared store at scale. JWTs embed claims in a signed token the client sends on every request — stateless and microservice-friendly, but hard to revoke before expiry. OAuth 2.0 is not authentication at all — it is delegated authorization that lets users grant third-party apps access without sharing passwords.

Confusing these three leads to security holes: putting sensitive data in JWTs, using OAuth when you need authentication, or building session stores when stateless tokens would suffice. This article compares all three — how they work, their trade-offs, and when to combine them in production.

JWTStateless tokenSelf-contained claimsSPAs, microservicesSessionServer-side stateSession ID in cookieTraditional web appsOAuth 2.0Delegated authorizationThird-party identitySign in with Google
JWT vs Session vs OAuth compared

JWT (JSON Web Token)

A JWT is a base64-encoded string with three parts: header (algorithm), payload (claims like userId and role), and signature (HMAC or RSA). The server signs the token at login; every subsequent request includes it as a Bearer token in the Authorization header. The server verifies the signature without hitting a database — making JWTs ideal for stateless APIs and microservices where any instance can validate any token.

The weakness is revocation. Once issued, a JWT is valid until it expires — even if the user changes their password or an admin disables the account. Short expiry times (15 minutes) plus refresh tokens mitigate this. Never store sensitive data in the JWT payload — it is base64, not encrypted. Anyone can decode it.

ClientLogin → JWTBearer token\non each requestVerify signature
JWT: signed token, no server session store

Quick reference

  • Best for: SPAs, mobile apps, microservices, API-to-API communication.
  • Strengths: stateless, horizontally scalable, works across domains, no session store needed.
  • Weaknesses: cannot revoke before expiry, token size grows with claims, XSS risk if stored in localStorage.
  • Store JWTs in httpOnly cookies (not localStorage) to prevent XSS theft.
  • Use short-lived access tokens (15 min) + refresh tokens for long sessions.
  • Sign with RS256 (asymmetric) when multiple services need to verify tokens.

Remember this

JWTs excel in distributed, stateless architectures — but plan for revocation and keep payloads minimal.

Session-Based Auth

Session auth stores user state server-side — in memory, Redis, or a database. On login, the server creates a session record and sends a session ID to the client as an httpOnly, Secure, SameSite cookie. Every request includes the cookie; the server looks up the session, validates it, and loads the user. Logout simply deletes the session — instant revocation.

This model is natural for traditional server-rendered apps (Rails, Django, ASP.NET MVC). It breaks down at scale when you need session affinity or a shared Redis cluster across regions. For a single-region web app with moderate traffic, sessions are simpler and more secure than JWTs because the server controls all state.

ClientCreate sessionSession storeCookie: sessionId
Session: server stores state, cookie holds ID

Quick reference

  • Best for: server-rendered web apps, admin dashboards, apps needing instant logout/revocation.
  • Strengths: instant revocation, server controls all state, smaller cookie (just an ID), simpler mental model.
  • Weaknesses: requires session store, sticky sessions or shared Redis, harder for mobile/native clients.
  • Use Redis for session storage in production — not in-memory stores that break on restart.
  • Set cookie flags: httpOnly, Secure, SameSite=Lax (or Strict for high-security apps).
  • Rotate session IDs after login to prevent session fixation attacks.

Remember this

Sessions are the simplest secure choice for traditional web apps where instant revocation matters.

OAuth 2.0

OAuth 2.0 solves a different problem: letting a user authorize a third-party app to access their data without sharing credentials. When you click Sign in with Google, your app redirects to Google, the user grants permission, and Google returns an authorization code. Your backend exchanges it for an access token and optionally an ID token (OpenID Connect) that proves who the user is.

OAuth is authorization, not authentication — though OpenID Connect (OIDC) adds an identity layer on top. Your app should never implement OAuth from scratch; use battle-tested libraries (Auth0, Keycloak, AWS Cognito, or NextAuth.js). The Authorization Code flow with PKCE is the standard for SPAs and mobile apps.

ClientUserAuth ServerYour APIUser grants access → access token → call API
OAuth: third-party authorization server

Quick reference

  • Best for: social login, third-party API access, enterprise SSO (SAML/OIDC), multi-tenant SaaS.
  • Strengths: no password storage, delegated trust, standardized flows, works with identity providers.
  • Weaknesses: complex to implement correctly, redirect flows, token management, provider dependency.
  • Always use Authorization Code + PKCE — never Implicit flow (deprecated and insecure).
  • Validate ID tokens (issuer, audience, expiry) when using OIDC for authentication.
  • Store OAuth tokens securely server-side — never expose refresh tokens to the browser.

Remember this

Use OAuth when users need to sign in via Google/GitHub or grant third-party API access — not for simple username/password login.

Key takeaway

Share:

In practice, production apps combine these models. A typical SPA uses OAuth for social login, issues JWT access tokens for API calls, and stores refresh tokens server-side. A traditional web app uses sessions with optional OAuth for social login. Choose based on client type (browser vs mobile vs service), revocation requirements, and scale — not because one pattern is universally better.

Related Articles

JSON Web Tokens are everywhere — issued by every OAuth 2.0 provider, sent in every Authorization: Bearer header, decoded

Read

Every REST API needs a way to verify who is calling it and what they are allowed to do. The method you choose shapes you

Read

Real-time communication between server and client breaks the standard HTTP request-response model. When you need live up

Read

Explore this topic

Keep learning

Follow a structured path or browse all courses to go deeper.