Compare server-side sessions with stateless JWTs for authenticating API requests. How do you handle logout and revocation in each?
Key points
- Sessions store state server side and hand the client an opaque id, so revocation is a delete and the token reveals nothingIn plain words: A session is a coat check ticket. The number means nothing by itself, and the desk can tear up its half whenever it likes
- JWTs carry signed claims so any service can verify them without a lookup, which scales horizontally and across servicesIn plain words: A JWT is a stamped wristband. Any door can check the stamp without phoning the front desk
- JWTs cannot be revoked before expiry without reintroducing state, so keep them short lived and pair with refresh tokensIn plain words: A wristband works until it wears off, so make it wear off quickly and hand out a new one at the desk
- Store tokens in HttpOnly, Secure, SameSite cookies for browsers to limit XSS exposureIn plain words: Keep the ticket in a locked pocket that page scripts cannot reach into
- Authorisation is separate, check permissions on every request against the resource, not just the token's validityIn plain words: Knowing who you are is not the same as letting you in. Each door still checks whether you may enter that room
Model answer
Server-side sessions. On login the server creates a session record (user id, expiry, device) in a store such as Redis and returns a random opaque session id in a cookie. Every request looks the session up. Logout deletes the record; "sign out of all devices" deletes all of a user's records. The cookie itself leaks nothing if stolen from logs. The cost is a lookup per request and a session store that every instance must reach, which is fine within one system but awkward across many independent services.
Stateless JWTs. On login the server signs a token containing claims (sub, exp, roles). Any service with the public key verifies the signature locally with no network call, which is why JWTs dominate service-to-service and multi-service architectures. The catch is revocation: a signed token is valid until exp no matter what the server thinks. Mitigations:
- Keep access tokens short (5–15 minutes) and issue a longer-lived refresh token stored server side; logout revokes the refresh token so the user is out within minutes.
- Maintain a small denylist of revoked token ids checked on sensitive endpoints, which reintroduces some state.
- Include a
versionclaim per user and bump it to invalidate everything.
Browser storage. Put the token in an HttpOnly; Secure; SameSite=Lax cookie so script cannot read it. localStorage is readable by any XSS payload. Cookies need CSRF protection; SameSite covers most of it.
Authentication is not authorisation. A valid token proves who is calling. Whether they may read this document is a per-request check against the resource's owner or an ACL, ideally centralised in one policy layer so every service enforces the same rules.
Pick sessions for a single web app that needs instant revocation; pick short-lived JWTs plus refresh tokens for APIs consumed by many services or mobile clients.
Likely follow-ups
- How would you rotate signing keys without logging everyone out?
- Where do you put authorization checks in a microservice architecture?