Signed Cookies and Session Tokens
Most web applications need to remember who a user is across multiple HTTP requests. HTTP itself is stateless — each request arrives with no memory of previous ones — so frameworks use either a session cookie or a self-contained token to carry identity. Understanding the two models, and the secrets that protect them, is foundational to building authentication that doesn't break or leak.
Stateful sessions vs self-contained tokens
In a stateful session, the server creates a session record in a database or cache (e.g., Redis) and issues the client an opaque session ID — a random value with no inherent meaning. On each request the client sends the ID back, and the server looks it up to find the associated user and data. The ID is worthless without the server-side record.
In a self-contained token model (like JWT), the server encodes all relevant information into the token itself and signs it. No server-side lookup is needed — the server just verifies the signature. The tradeoff is that a token cannot be invalidated before it expires; you can only wait for the expiry or maintain a blocklist, partially defeating the "stateless" benefit.
Signed cookies sit in the middle: the cookie value is self-contained and signed, but the payload is typically just a session ID or simple user data that the server can verify without a database round-trip.
How cookie signing works
A signed cookie appends an HMAC tag to the cookie value before sending it to the browser. When the browser returns the cookie, the server recomputes the HMAC and confirms the two match. If an attacker modifies the cookie value, the HMAC will not match and the server rejects it.
A simple signed cookie looks like:
session=eyJ1c2VyIjoxMjM0fQ.Zx9mVQ2aKpL8nRjTcEwO1hYdGs3iBfUe
The part before the dot is the Base64-encoded payload; the part after is the HMAC signature. Frameworks like Express (via cookie-session or express-session) and Rails (via encrypted signed cookies) handle this automatically, but the signing secret you provide is what keeps the signature trustworthy.
The signing secret
The signing secret is an HMAC key used to produce and verify cookie signatures. It must be:
- Random — generated from a CSPRNG, not a human-chosen phrase.
- Long enough — at least 256 bits (32 bytes) for HMAC-SHA256.
- Secret — stored in an environment variable or secret manager, never in source code or config files committed to version control.
Some frameworks use the signing secret to also encrypt cookie values, not just sign them. Encryption hides the payload from the user; signing only prevents tampering. Both are useful depending on whether you want users to be able to read their own session data.
Required cookie security attributes
A signed cookie is only as safe as the HTTP attributes attached to it:
HttpOnly— prevents JavaScript from reading the cookie. Blocks XSS attacks from stealing session tokens. Always set this.Secure— the cookie is only sent over HTTPS connections. Prevents transmission over unencrypted HTTP. Always set this in production.SameSite=StrictorLax— controls whether the cookie is sent on cross-site requests.Laxis the safe default;Strictadds protection but can break OAuth redirects. Prevents CSRF attacks.Max-AgeorExpires— session cookies (no expiry) are deleted when the browser closes; persistent cookies survive restarts. Choose based on how long you want the session to live.__Host-prefix — browsers enforce that cookies with this prefix are alwaysSecure, have noDomainattribute, and havePath=/. Use it for session cookies on your main domain.
When to use sessions vs JWTs
Choose stateful sessions when you need immediate revocation — when a user logs out, deletes their account, or has suspicious activity, the session record is deleted and the next request fails. This is the safest model for most web applications.
Choose JWTs when you have multiple independent services that need to verify identity without sharing a session store, or when you control token lifetime tightly (short expiry + refresh tokens). Accept that immediate revocation requires extra infrastructure (a blocklist or very short token lifetimes).
Signed cookies are a good fit for monolithic web apps and server-rendered pages where simplicity matters. JWTs suit API-first architectures with multiple backends or mobile clients.
Need a session signing secret? Generate a 256-bit or 512-bit HMAC key right in your browser.
Open the key generator