Session vs Token Authentication
Session authentication stores state server-side behind an opaque cookie, while token authentication carries a signed or opaque credential. The choice affects revocation, scaling, and XSS exposure.
Definition
Session authentication issues an opaque session identifier, usually in a cookie, and keeps user state on the server. Token authentication issues a self-contained or opaque credential that the client presents on each request, allowing verification with less or no per-request server lookup. Both models can be secure; their threats and operational costs differ.
Context and scope
The choice appears in browser applications, mobile clients, API gateways, and service-to-service calls. Many systems use both: a login establishes a server session, while backend services exchange tokens.
Common misconceptions
- Token authentication is inherently more secure than cookie-based sessions
- Stateless tokens require no server-side storage at all for revocation or refresh
Anti-patterns
- Storing long-lived bearer tokens in localStorage where any script can read them
- Using a stateless token with a long expiry to avoid building revocation
Related concepts
Related examples
Authoritative source
https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html
How each model works
Session authentication gives the browser an opaque session ID in a cookie. The server stores user state and looks it up on each request. Token authentication gives the client a signed or opaque token, commonly sent as Authorization: Bearer ...; the server verifies it and may keep no per-request state.
When to use each
Choose server sessions for browser applications on the same site that need immediate logout and fine-grained session control. Choose tokens for APIs, mobile apps, service-to-service calls, and cross-domain clients. Many systems combine both: an OpenID Connect login creates a server session, while internal services exchange tokens. Compare revocation: deleting a session record is instant, while revoking a stateless JWT requires a denylist or short lifetimes.
Trade-offs
Sessions need a shared store such as Redis to scale horizontally, and cookie-based sessions need CSRF protection plus HttpOnly, Secure, and SameSite attributes. Tokens scale verification cheaply but are bearer credentials: anyone who steals one can use it. Storing tokens in localStorage exposes them to XSS, while HttpOnly cookies avoid that but reintroduce CSRF concerns. Stateless tokens trade revocation latency for fewer database reads.
Example
app.use(session({
secret: process.env.SESSION_SECRET,
cookie: { httpOnly: true, secure: true, sameSite: 'lax' },
store: new RedisStore({ client: redis }),
}));
A token API instead validates Authorization: Bearer <jwt> on every call and checks exp, aud, and iss.
Misconceptions and related concepts
Tokens are not automatically safer than sessions; the threat model differs. “Stateless” does not mean no storage, because refresh tokens, signing keys, and denylists still exist. Sessions do scale with a shared store. Related concepts include JWT, CSRF, SameSite cookies, and OpenID Connect.