How do cookies work for sessions, and what do HttpOnly, Secure, and SameSite do?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
The server sets a session id via Set-Cookie; the browser stores it and automatically attaches it to matching requests, so stateless HTTP gains memory. HttpOnly hides the cookie from JavaScript (XSS defense), Secure restricts it to HTTPS, and SameSite controls cross-site sending (Lax default, Strict tightest, None for embedded flows) — the primary CSRF defense.
Detailed explanation
HTTP is stateless, so login state needs a carrier. On successful login the server creates a session record (in memory, Redis, or a signed token) and returns Set-Cookie: sessionId=abc; Path=/; HttpOnly; Secure; SameSite=Lax. The browser files it in the cookie jar keyed by domain and path, then attaches Cookie: sessionId=abc to every subsequent matching request automatically — including images and fetch calls, which is both the convenience and the danger. Lookup on the server restores who you are. The flags each close a hole: HttpOnly removes document.cookie access, so an injected XSS script cannot steal the session (it can still act as you while the page lives, but the token never leaks). Secure forbids sending over plain HTTP, killing network sniffing. SameSite governs cross-site attachment: Strict never sends on cross-site navigation (safest, but breaks login-via-SSO return flows); Lax (the modern default) sends on top-level GET navigation but not on POSTs or subresource loads — blocking classic CSRF while keeping links working; None allows cross-site sending but requires Secure, used by embedded widgets and third-party flows. Session expiry is two clocks: Max-Age/Expires for the browser copy, and server-side TTL — log out must destroy the server record, not just delete the cookie. Alternatives worth naming: bearer tokens in Authorization headers (no auto-attach, immune to CSRF, but XSS-stealable from storage) and the modern split — HttpOnly refresh cookie plus short-lived in-memory access token.
Example
# Login response sets the session cookie
HTTP/1.1 200 OK
Set-Cookie: sessionId=abc123; Path=/; Max-Age=86400; HttpOnly; Secure; SameSite=Lax
# Every later request carries it automatically — even ones the page didn't intend:
GET /account HTTP/1.1
Cookie: sessionId=abc123
# An evil-site form POST to your bank sends cookies too → that's CSRF,
# which is exactly what SameSite=Lax blocks for non-GET requests.Interview tip
Explain the auto-attach behavior first — it motivates every flag. Then map each flag to its attack: HttpOnly→XSS theft, Secure→sniffing, SameSite→CSRF. That mapping is the whole answer.
Common mistakes
- Storing JWTs in localStorage while calling it safe from CSRF but ignoring XSS theft.
- Logging out by deleting the cookie client-side while the server session stays valid.
- Using SameSite=None without Secure, which modern browsers reject.