API design
JWT vs session authentication
Short answer
Use secure, server-side sessions for browser applications when immediate logout and revocation matter. Use short-lived JWTs for controlled APIs or services that need local verification across boundaries, and pair them with refresh rotation, audience checks, key rotation, and a revocation strategy.
Written and reviewed by Sahil Srivastav
What each one actually is
A session stores authentication state on the server and gives the client an opaque cookie or identifier. The server can revoke or change the session immediately.
A JWT carries signed claims that a verifier can validate without a session lookup. It is self-contained, but claims remain valid until expiry unless the system adds a denylist or changes keys.
Neither format fixes authorization by itself. Validate issuer, audience, expiry, signature, and permissions, and keep credentials out of URLs and logs.
Side by side
| JWT authentication | Session authentication | |
|---|---|---|
| Revocation | Delete or disable server record immediately | Needs expiry, denylist, or key change |
| Per-request lookup | Usually session-store read | Local signature and claim validation |
| Payload | Opaque small cookie | Claims travel with every request |
| Browser safety | HttpOnly, Secure, SameSite cookie pattern | Storage choice can create XSS exposure |
| Horizontal scale | Shared session store or affinity | Local verification; key distribution required |
| Logout | Immediate server-side invalidation | Often effective only after token expiry |
| Token size | Small identifier | Grows with claims and nested data |
| Best fit | First-party web sessions | Short-lived service and API credentials |
Choose JWT authentication when
- A first-party browser app needs immediate logout or account disable
- The organisation can operate a small session store
- You want opaque credentials with minimal claim leakage
- CSRF protections and cookie policy are already part of the web stack
Choose Session authentication when
- Independent services need to verify a short-lived identity locally
- A controlled API has explicit issuer, audience, and key rotation rules
- The system accepts bounded revocation latency
- A gateway can issue and rotate tokens without putting secrets in clients
The trade-off in detail
JWTs are easy to verify but hard to revoke selectively. A five-minute access token limits exposure; a long-lived JWT turns every permission change into an incident response problem.
Sessions add a lookup and a dependency, but that dependency buys control. Use TTLs, bounded storage, replication, and failure policy rather than moving revocation complexity into every service.
A JWT is signed, not encrypted by default. Claims can be read by the holder, and a valid token can be replayed; keep sensitive data out and use TLS and audience restrictions.
Things that are commonly said and are wrong
- “JWT is more secure than sessions.” Security follows storage, validation, expiry, CSRF, XSS, and revocation design.
- “Signing a JWT hides its contents.” JWS claims are readable; encryption is a separate JOSE mode.
- “Stateless authentication has no server state.” Keys, denylist entries, refresh tokens, and user permissions still create state somewhere.
FAQ
Should a React web app use JWTs in localStorage?
Usually use an HttpOnly, Secure, SameSite session cookie instead. If an API requires bearer tokens, keep access tokens short-lived and protect refresh handling against XSS and replay.
Can JWTs be revoked?
Yes, with a denylist, token version, short expiry, or key rotation, but each adds state or invalidates more tokens. Choose the mechanism explicitly.
Do sessions prevent CSRF?
No. Cookie-authenticated state-changing requests still need SameSite policy and CSRF protection where the browser can send the cookie cross-site.