API design

JWT vs session authentication

API designAuthenticationDecision guide

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 authenticationSession authentication
RevocationDelete or disable server record immediatelyNeeds expiry, denylist, or key change
Per-request lookupUsually session-store readLocal signature and claim validation
PayloadOpaque small cookieClaims travel with every request
Browser safetyHttpOnly, Secure, SameSite cookie patternStorage choice can create XSS exposure
Horizontal scaleShared session store or affinityLocal verification; key distribution required
LogoutImmediate server-side invalidationOften effective only after token expiry
Token sizeSmall identifierGrows with claims and nested data
Best fitFirst-party web sessionsShort-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.

Decide it in a real repository

Choosing correctly on a whiteboard and enforcing the choice in code are different skills. Gronex ships broken backend repositories whose tests assert the invariant, not the happy path.

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.

Other decisions engineers weigh