Session Management & Cookies
Sessions let a server remember who you are between requests. The browser stores a cookie with a random session ID; the server uses it to look up your session data.
Practical note: these issues usually slip through because everything looks “fine” in happy-path testing — until one weird request hits production.
Beginner mental hook: Cookie = “key”; Session store = “lockbox.” If the key is stolen or reused incorrectly, the attacker becomes you.
Mental model
- Login: server creates session data and sets a cookie containing a random session ID.
- Request: browser automatically sends the cookie to the server.
- Server: looks up session ID in the session store and decides identity/permissions.
- Logout: server destroys session and clears cookie.
- Cookie flags:
HttpOnly,Secure,SameSite. - Rotation: regenerate session ID at login and privilege changes (anti-fixation).
- CSRF: because cookies are auto-sent, state-changing requests need CSRF strategy.
Common failure modes (what goes wrong)
A) Session fixation (no rotation)
- Root cause: session ID is not regenerated at login/privilege escalation.
- Attacker mindset: “Can I make the victim authenticate into a session ID I already know?”
- Defense: regenerate session on login and on privilege changes; deny session reuse.
B) Insecure cookie settings
- Root cause: missing
HttpOnly(JS access), missingSecure(sent over HTTP), weakSameSite. - Impact: session theft and CSRF risk increases.
- Defense: HttpOnly+Secure, appropriate SameSite, short TTL, and strong session IDs.
C) Weak invalidation / long TTLs
- Root cause: logout doesn’t destroy server session; session TTL too long; no device/session listing.
- Defense: destroy server-side sessions on logout; idle + absolute timeouts; allow per-device sign-out.
D) CSRF confusion
- Root cause: cookie-based auth used without CSRF protections for state-changing actions.
- Defense: CSRF tokens, SameSite, and safe HTTP methods; consider step-up for high-risk actions.
Defensive patterns (Node.js)
Secure session setup (Express)
import session from "express-session";
app.set("trust proxy", 1); // if behind a reverse proxy
app.use(session({
name: "sid",
secret: process.env.SESSION_SECRET, // high entropy, rotated
resave: false,
saveUninitialized: false,
cookie: {
httpOnly: true,
secure: true,
sameSite: "lax",
maxAge: 60 * 60 * 1000, // 1 hour
}
})); Rotate on login (prevents fixation)
app.post("/login", async (req, res) => {
const user = await authenticate(req.body);
if (!user) return res.status(401).send("bad credentials");
req.session.regenerate(() => { // âś… new session ID
req.session.userId = user.id;
req.session.authTime = Date.now();
res.send("ok");
});
}); Destroy on logout
app.post("/logout", (req, res) => {
req.session.destroy(() => {
res.clearCookie("sid");
res.send("logged out");
});
}); Guardrails: rotate, set cookie flags, set TTLs, and pair cookie-based auth with CSRF strategy.
Safe validation (defensive verification)
- Confirm session IDs are random, not predictable, and stored server-side (not user-controlled).
- Confirm session rotation at login and privilege changes.
- Confirm cookie flags: HttpOnly, Secure, appropriate SameSite; no sessions over HTTP in prod.
- Confirm logout destroys server sessions and clears cookies.
- Confirm idle + absolute timeouts and “active sessions” management.
- Confirm CSRF protections for state-changing endpoints when using cookie-based auth.
Interview Questions & Answers (Easy → Hard)
Easy
- What is a session?
A: Plain: server memory of login. Deep: session ID cookie maps to server-side data. - Why HttpOnly?
A: Plain: prevents JS reading cookies. Deep: reduces session theft via XSS (not a full fix for XSS). - Why Secure?
A: Plain: cookie only over HTTPS. Deep: prevents network sniffing on HTTP links/misconfig. - What is SameSite?
A: Plain: limits cross-site cookie sending. Deep: reduces CSRF risk; choose Lax/Strict based on UX. - What is logout supposed to do?
A: Plain: end session. Deep: destroy server session + clear cookie. - Session vs JWT?
A: Plain: server vs token. Deep: sessions simplify revocation; JWT needs lifecycle controls. - Why rotate session IDs?
A: Plain: stop fixation. Deep: prevents pre-set IDs becoming authenticated.
Medium
- Scenario: session ID not regenerated on login. Risk?
A: Plain: fixation. Deep: victim logs into attacker-known session ID; fix with regenerate. - Scenario: long session TTL. Risk?
A: Plain: stolen sessions last longer. Deep: tighten TTL; add idle/absolute timeouts and revocation events. - Scenario: cookie-based auth, no CSRF tokens. Risk?
A: Plain: CSRF. Deep: cookies auto-send; protect state-changing routes with CSRF strategy. - Follow-up: Lax vs Strict?
A: Plain: strict blocks more. Deep: Lax is common baseline; pair with CSRF tokens for sensitive actions. - Scenario: “Remember me” implemented as a long cookie. Fix?
A: Plain: use refresh-like server state. Deep: persistent token bound to device with revocation and rotation. - Follow-up: where to store sessions?
A: Plain: central store. Deep: Redis/DB session store for scale; TTL-managed; revokeable. - Scenario: session stolen. What should happen?
A: Plain: detect/revoke. Deep: anomaly detection, forced logout, step-up on risky actions.
Hard
- How do you design session revocation at scale?
A: Plain: central tracking. Deep: server-side store + per-device sessions + revoke on events + telemetry. - How do you prevent session replay across devices?
A: Plain: bind to device signals. Deep: device/session IDs, rotate tokens, detect impossible travel, and step-up. - How do you secure “change email/password” endpoints?
A: Plain: require extra checks. Deep: step-up + recent auth + CSRF + session rotation after change. - What telemetry matters?
A: Plain: unusual logins. Deep: session creation spikes, failed CSRF, device changes, abnormal IP patterns. - Scenario: reverse proxy + Secure cookies issues. Fix?
A: Plain: trust proxy config. Deep: set trust proxy and ensure HTTPS termination is correct so cookies are Secure. - When choose BFF pattern?
A: Plain: to avoid tokens in browser. Deep: web app uses server session; backend calls APIs with tokens safely server-side.
Exploitation progression (attacker mindset)
- Steal or set a session: attackers look for weak cookie flags, XSS, or fixation opportunities.
- Keep it valid: long TTLs and no invalidation make stolen sessions valuable.
- Trigger actions: cookie auto-sending means CSRF becomes a common chain for state changes.
- Escalate: missing step-up on sensitive actions enables account changes from a stolen session.
Checklist
- Rotate session on login and privilege change.
- HttpOnly + Secure + SameSite cookie flags set correctly in production.
- Logout destroys server-side session; short idle + absolute timeouts.
- Active session listing + per-device sign-out available.
- CSRF protections for state-changing routes when using cookies.
- Step-up authentication for sensitive operations (email/password/MFA changes).
Remediation playbook
- Enable strict cookie flags and enforce HTTPS-only cookies.
- Implement session rotation at login and privilege transitions.
- Add idle + absolute timeouts; ensure logout destroys server session state.
- Add CSRF protection to state-changing endpoints if cookie-based auth is used.
- Add “active sessions” management and revoke sessions on password reset/security events.
- Add tests for rotation, invalidation, and CSRF enforcement.