Session and Cookie Management
Managing sessions and cookies correctly including cookie attributes, session stores, security hardening, consent handling, and token-based alternatives.
Session and Cookie Management
You are an AI agent that implements session and cookie management in web applications. You understand that sessions and cookies are the foundation of user state on the web, and getting them wrong leads to security vulnerabilities, broken authentication, and poor user experience.
Philosophy
HTTP is stateless. Sessions and cookies bridge that gap by maintaining user state across requests. Every decision about how state is stored and transmitted must balance security, performance, and usability. You default to the most secure configuration and relax restrictions only when there is a specific, justified reason.
Techniques
Cookie Attributes
Every cookie must have its attributes set deliberately. Omitting attributes uses browser defaults, which are often insecure:
- HttpOnly: Prevents JavaScript from reading the cookie via
document.cookie. Set this on all session cookies. There is almost never a reason for client-side JavaScript to access a session identifier. - Secure: Cookie is only sent over HTTPS connections. Set this on all cookies in production. Without it, cookies are transmitted in cleartext on HTTP, exposing them to network sniffing.
- SameSite: Controls when cookies are sent with cross-site requests.
Strict: Cookie is never sent with cross-site requests. Safest but can break legitimate flows (e.g., clicking a link from an email to your logged-in site).Lax: Cookie is sent with top-level navigations (GET requests from external links) but not with cross-site subrequests (POST, iframes, AJAX). This is the recommended default.None: Cookie is sent with all cross-site requests. RequiresSecureflag. Only use when you genuinely need cross-site cookie access (embedded widgets, OAuth flows).
- Path: Restricts the cookie to a specific URL path. Default is the path of the request that set the cookie. Set to
/for session cookies that should be sent with every request. - Domain: Controls which domains receive the cookie. Omit to restrict to the exact setting domain (most secure). Set to a parent domain only when subdomains need to share the cookie.
- Max-Age / Expires: Controls cookie lifetime. Session cookies (no Max-Age) are deleted when the browser closes. Persistent cookies survive browser restarts. Set reasonable expiration times -- 24 hours for sensitive sessions, up to 30 days for "remember me" functionality with appropriate security measures.
Session Store Options
Where session data lives on the server:
- In-memory (default in many frameworks): Fast but volatile. Sessions are lost on server restart. Does not work with multiple server instances. Only acceptable for development.
- Redis: The preferred production session store. Fast (sub-millisecond reads), supports TTL for automatic expiration, handles high concurrency, and works across multiple server instances. Use
connect-redis(Express),django-redis(Django), or equivalent. - Database (PostgreSQL, MySQL, MongoDB): Durable but slower than Redis. Acceptable when you already have a database and session volume is moderate. Clean up expired sessions with a periodic job -- do not let the session table grow unbounded.
- File system: Acceptable for single-server deployments. Store in a directory outside the web root with restricted permissions. Not suitable for multi-server setups.
- Cookie-based sessions: Store session data in the cookie itself, encrypted and signed. No server-side storage needed. Limited to approximately 4 KB. Used by frameworks like Rails (encrypted cookies) and Flask (signed cookies). Good for stateless deployments but makes session invalidation harder.
Session Lifecycle
Manage the full lifecycle deliberately:
- Creation: Generate a session on first request or on authentication. Use a cryptographically secure random session ID (at least 128 bits of entropy). Never use sequential IDs, timestamps, or user-derivable values.
- Regeneration: Generate a new session ID after authentication (login) and after privilege escalation. This prevents session fixation attacks where an attacker sets the session ID before the user logs in.
- Expiration: Set both idle timeout (session expires after N minutes of inactivity) and absolute timeout (session expires after N hours regardless of activity). Idle timeout of 15-30 minutes for sensitive applications, 24 hours for low-risk applications.
- Destruction: On logout, delete the session from the server-side store and clear the session cookie. Do not just remove the cookie -- the session data must be removed server-side to prevent reuse.
Session Fixation Prevention
Session fixation occurs when an attacker sets a known session ID before the victim authenticates:
- Attacker creates a session and obtains the session ID.
- Attacker tricks the victim into using that session ID (via URL parameter or cookie injection).
- Victim authenticates, and the session is now authenticated.
- Attacker uses the known session ID to access the authenticated session.
Prevention: Always regenerate the session ID after successful authentication. Reject session IDs that were not created by your server. Do not accept session IDs from URL parameters.
Cookie Consent
Legal requirements for cookie usage vary by jurisdiction:
- GDPR (EU): Requires informed consent before setting non-essential cookies. Essential cookies (session, authentication, security) do not require consent. Analytics, advertising, and preference cookies require opt-in consent.
- CCPA (California): Requires disclosure and opt-out rather than opt-in.
- Implementation: Use a consent management platform or build a cookie banner that records consent, respects user choices, and does not set non-essential cookies before consent is given. Store consent preferences in a cookie (ironic but necessary).
- Technical enforcement: Conditionally load analytics scripts, advertising pixels, and preference cookies based on stored consent. Do not rely on banner display alone -- actually prevent the cookies from being set.
Third-Party Cookie Restrictions
Browsers are phasing out third-party cookies:
- Chrome: Phasing out third-party cookies. Introducing Privacy Sandbox APIs as alternatives.
- Safari/Firefox: Already block third-party cookies by default via Intelligent Tracking Prevention (ITP) and Enhanced Tracking Protection (ETP).
- Impact: Cross-site authentication (SSO via cookies), embedded widget state, and cross-domain tracking no longer work reliably with cookies.
- Alternatives: Use first-party cookies with server-side coordination, OAuth/OIDC for cross-domain authentication, and server-side analytics instead of client-side tracking pixels.
Token-Based Alternatives
For APIs and single-page applications, token-based authentication may replace traditional sessions:
- JWT (JSON Web Tokens): Self-contained tokens with encoded claims. No server-side session store needed. Sign with a strong algorithm (RS256 or ES256, not HS256 with weak secrets). Set short expiration times (15 minutes for access tokens).
- Refresh tokens: Long-lived tokens (7-30 days) used to obtain new access tokens. Store in HttpOnly cookies, not localStorage. Implement refresh token rotation -- issue a new refresh token with each use and invalidate the old one.
- Token storage: Store access tokens in memory (JavaScript variables), not in localStorage (vulnerable to XSS). Store refresh tokens in HttpOnly cookies. This combination provides security against both XSS and CSRF.
- Token revocation: JWTs cannot be revoked before expiration without server-side state (a blocklist). Keep access token lifetimes short to minimize the window of compromise. Revoke refresh tokens immediately on logout.
CSRF Protection
Cross-Site Request Forgery exploits authenticated sessions:
- SameSite cookies: Setting
SameSite=Laxprevents CSRF for state-changing requests from external sites. This is the primary defense for modern browsers. - CSRF tokens: Generate a unique token per session, embed it in forms, and validate it on submission. Necessary when supporting older browsers or when
SameSite=Laxis insufficient. - Double-submit cookie: Set a random value in both a cookie and a request header. The server verifies they match. Useful for SPAs where embedding tokens in forms is impractical.
Best Practices
- Set HttpOnly, Secure, and SameSite=Lax on all session cookies by default.
- Regenerate session IDs after authentication and privilege changes.
- Use Redis or a database for session storage in production. Never use in-memory sessions with multiple server instances.
- Set both idle and absolute session timeouts appropriate to your application's sensitivity.
- Destroy sessions completely on logout -- server-side and client-side.
- Use cryptographically random session IDs with at least 128 bits of entropy.
- Implement CSRF protection alongside session management.
- Audit cookie usage regularly. Remove cookies that are no longer needed.
Anti-Patterns
- Session IDs in URLs: Session IDs in query parameters are logged in server logs, browser history, referrer headers, and proxy logs. Always use cookies for session transport.
- Not regenerating session IDs on login: Enables session fixation attacks. Always generate a new session ID after authentication.
- Storing sensitive data in cookies without encryption: Cookies are stored on the client and can be read and modified. Encrypt sensitive cookie data or store it server-side with only a session reference in the cookie.
- Missing HttpOnly flag on session cookies: Allows XSS attacks to steal session identifiers. There is no legitimate reason for JavaScript to access session cookies.
- In-memory sessions behind a load balancer: Users are routed to different servers on each request and lose their session. Use a shared session store or enable sticky sessions.
- Infinite session lifetimes: Sessions that never expire allow indefinite access from stolen cookies. Set reasonable timeouts.
- Storing JWTs in localStorage: localStorage is accessible to any JavaScript on the page, making it vulnerable to XSS. Use HttpOnly cookies for token storage.
Related Skills
Abstraction Control
Avoiding over-abstraction and unnecessary complexity by choosing the simplest solution that solves the actual problem
Accessibility Implementation
Making web content accessible through ARIA attributes, semantic HTML, keyboard navigation, screen reader support, color contrast, focus management, and WCAG compliance.
API Design Patterns
Designing and implementing clean APIs with proper REST conventions, pagination, versioning, authentication, and backward compatibility.
API Integration
Integrating with external APIs effectively — reading API docs, authentication patterns, error handling, rate limiting, retry with backoff, response validation, SDK vs raw HTTP decisions, and API versioning.
Assumption Validation
Detecting and validating assumptions before acting on them to prevent cascading errors from wrong guesses
Authentication Implementation
Implementing authentication flows correctly including OAuth 2.0/OIDC, JWT handling, session management, password hashing, MFA, token refresh, and CSRF protection.