Best Practices

AI Rules for Session Management

AI generates sessions with no expiration, no server-side store, and logout that only clears the cookie. Rules for server-side sessions, idle/absolute timeouts, regeneration, and concurrent session control.

7 min read·January 25, 2025

Sessions that never expire, logout that clears only the cookie, no idle timeout

Redis sessions, idle + absolute timeouts, regeneration, concurrent limits, secure cookies

AI Manages Sessions Like They Are Immortal

AI generates sessions with: no expiration (session lives forever), client-side storage only (cookie or localStorage is the session), no server-side store (server cannot invalidate sessions), logout that clears the client cookie only (session still valid server-side), no idle timeout (abandoned session stays active), and no regeneration on privilege change (same session ID before and after login). Each of these is a security weakness with a standard solution.

Modern session management is: server-stored (Redis or database — server controls the session lifecycle), time-limited (idle timeout 30min + absolute timeout 24h), regenerated (new session ID on login, role change, and password change), concurrent-limited (max 3 active sessions per user), and fully destroyable (logout kills the session server-side, not just the cookie). AI generates none of these.

These rules cover: server-side session stores, idle and absolute timeouts, session regeneration for fixation prevention, concurrent session limits, and secure cookie configuration.

Rule 1: Server-Side Session Store (Redis)

The rule: 'Store session data server-side in Redis or a database. The client holds only a session ID (random, opaque, in an httpOnly cookie). All session data — user ID, role, permissions, last activity — lives on the server. This gives you: instant invalidation (delete the session from Redis), cross-server sessions (any server can read from Redis), and tamper-proof data (client cannot modify session state).'

For Redis vs database: 'Redis: sub-millisecond reads, built-in TTL for automatic expiration, ideal for session stores. Database (Postgres): durable, queryable (find all sessions for a user), no extra infrastructure. Use Redis for high-traffic apps (thousands of concurrent sessions). Use the database for simpler deployments where sub-millisecond reads are not critical.'

AI generates: express-session with the default MemoryStore — a warning in the console says 'MemoryStore is not designed for production' because it leaks memory and does not scale. Sessions vanish on server restart. Redis-backed sessions persist across restarts, scale across servers, and auto-expire via TTL.

  • Client holds session ID only — opaque, random, httpOnly cookie
  • Server stores session data — user ID, role, permissions, last activity timestamp
  • Redis for production — sub-millisecond reads, TTL-based expiration, cross-server
  • Database fallback for simpler deployments — queryable, durable, no extra infra
  • Never MemoryStore in production — memory leaks, no persistence, no scaling
💡 Redis TTL = Auto-Cleanup

Redis SET with EX (expire) means sessions auto-delete when they timeout. No cleanup cron, no stale session buildup, no memory leaks. SET session:abc123 '{data}' EX 1800 — session expires in 30 minutes automatically.

Rule 2: Idle and Absolute Timeouts

The rule: 'Implement two timeout mechanisms: idle timeout (30 minutes of inactivity) and absolute timeout (24 hours regardless of activity). Idle timeout: if the user has not made a request in 30 minutes, destroy the session. This protects against abandoned sessions (user walks away from an unlocked computer). Absolute timeout: even with continuous activity, force re-authentication after 24 hours. This limits the blast radius of a stolen session.'

For sliding vs fixed: 'Idle timeout uses a sliding window — each request resets the 30-minute timer. The user stays logged in as long as they are active. Absolute timeout is fixed from login time — no resets. Combine both: session.lastActivity (checked on every request, reset on activity) and session.createdAt (checked on every request, never reset). Either expiration destroys the session.'

AI generates sessions with no timeout — or sets a cookie maxAge of 30 days. A stolen session cookie works for a month. With idle + absolute timeouts: a stolen cookie from an abandoned session expires in 30 minutes. An actively-used stolen session expires in 24 hours. Defense in depth — two independent clocks protecting the user.

Rule 3: Session Regeneration on Privilege Change

The rule: 'Regenerate the session ID on every privilege escalation: login, role change, password change, and MFA completion. The old session ID becomes invalid. In Express: req.session.regenerate(callback). In Next.js with NextAuth: session token rotation is automatic on sign-in. This prevents session fixation attacks.'

For the session fixation attack: 'Attacker obtains a valid session ID (by visiting the login page and capturing the pre-login session cookie). Attacker tricks the victim into using that session ID (via a crafted link with the session ID in the URL or by setting the cookie via XSS). Victim logs in — the session is now authenticated. Attacker uses the known session ID — now authenticated as the victim. Regeneration breaks this: the pre-login session ID is invalidated on login.'

AI generates login handlers that authenticate the user into the existing session — same session ID before and after login. The session fixation attack requires no special tools or skills. Session regeneration is one function call: req.session.regenerate(). One line of code prevents an entire class of authentication bypass attacks.

⚠️ One Line Prevents Fixation

Session fixation: attacker sets a known session ID, victim logs in, attacker uses the now-authenticated session. req.session.regenerate() — one function call on login. The pre-login session ID is invalidated. Attack requires no tools; prevention requires one line.

Rule 4: Concurrent Session Limits

The rule: 'Limit concurrent sessions per user — typically 3-5 active sessions (desktop, phone, tablet). On new login beyond the limit, either: (1) reject the login (show active sessions, ask user to end one), or (2) terminate the oldest session automatically. Provide a session management page where users can view and revoke their active sessions — showing: device/browser, IP address, last activity, and a revoke button.'

For session tracking: 'Store sessions with metadata: { sessionId, userId, userAgent, ip, lastActivity, createdAt }. On login: count active sessions for the user. On session management page: list all sessions, highlight the current one (cannot revoke yourself). On revoke: delete the session from Redis. On password change: revoke all sessions except the current one.'

AI generates unlimited sessions with no tracking. A compromised account can have 100 active sessions — the attacker, the user, automated scripts — and nobody knows. Concurrent limits + session management give users visibility and control. They can see if someone else is logged in and revoke suspicious sessions immediately.

  • Max 3-5 concurrent sessions per user — desktop, phone, tablet covers most users
  • On new login beyond limit: reject or terminate oldest session
  • Session management page: device, IP, last activity, revoke button
  • On password change: revoke all sessions except current
  • Track session metadata: userAgent, IP, createdAt, lastActivity

Complete Session Management Rules Template

Consolidated rules for session management.

  • Server-side session store (Redis) — client holds opaque session ID only
  • Idle timeout (30min) + absolute timeout (24h) — two independent clocks
  • Regenerate session ID on login, role change, password change, MFA completion
  • Concurrent session limit (3-5) — with user-facing session management page
  • On password change: revoke all sessions except current
  • httpOnly + secure + SameSite=Lax + path=/ — four flags, four protections
  • Never MemoryStore in production — Redis for persistence, scaling, TTL
  • Session metadata: userAgent, IP, lastActivity — for audit and user visibility