Session Management
Server-side session handling, cookie security, session stores, and fixation prevention
You are an expert in session-based authentication for securing web applications. You understand server-side session stores, cookie configuration, session lifecycle management, and defense against session-based attacks. ## Key Points - **Session ID**: A cryptographically random, opaque identifier (minimum 128 bits of entropy) sent to the client. - **Session Store**: Server-side storage for session data — in-memory, Redis, database, or encrypted cookies. - **Session Cookie**: The HTTP cookie carrying the session ID, configured with security attributes. - **Session Lifecycle**: Creation at login, validation on each request, renewal on privilege change, destruction at logout. - **Session Fixation**: An attack where an adversary sets a known session ID before the victim authenticates. - **Idle Timeout vs Absolute Timeout**: Idle timeout expires unused sessions; absolute timeout caps total session duration. 1. **Generate session IDs with a CSPRNG** — never use predictable or sequential identifiers. 2. **Regenerate the session ID after login** and after any privilege elevation to prevent session fixation. 3. **Set `HttpOnly`, `Secure`, `SameSite=Strict`** on session cookies. Use the `__Host-` cookie prefix where possible. 4. **Implement both idle and absolute timeouts**. Idle: 15–30 minutes. Absolute: 8–12 hours. 5. **Use an external session store** (Redis, Memcached) for production. In-memory stores do not survive restarts and cannot scale horizontally. 6. **Destroy sessions completely on logout** — delete from the store and clear the cookie.
skilldb get auth-patterns-skills/Session ManagementFull skill: 168 linesSession Management — Authentication & Authorization
You are an expert in session-based authentication for securing web applications. You understand server-side session stores, cookie configuration, session lifecycle management, and defense against session-based attacks.
Core Philosophy
Overview
Session-based authentication associates a server-side state record with a client-side session identifier, typically transmitted via an HTTP cookie. When a user authenticates, the server creates a session record containing user identity and metadata, then issues a session ID to the client. Every subsequent request includes this ID, allowing the server to look up the associated session. This pattern provides strong revocation guarantees because session state lives on the server.
Core Concepts
- Session ID: A cryptographically random, opaque identifier (minimum 128 bits of entropy) sent to the client.
- Session Store: Server-side storage for session data — in-memory, Redis, database, or encrypted cookies.
- Session Cookie: The HTTP cookie carrying the session ID, configured with security attributes.
- Session Lifecycle: Creation at login, validation on each request, renewal on privilege change, destruction at logout.
- Session Fixation: An attack where an adversary sets a known session ID before the victim authenticates.
- Idle Timeout vs Absolute Timeout: Idle timeout expires unused sessions; absolute timeout caps total session duration.
Implementation Patterns
Express.js with Redis Session Store
const session = require('express-session');
const RedisStore = require('connect-redis').default;
const { createClient } = require('redis');
const redisClient = createClient({ url: process.env.REDIS_URL });
redisClient.connect();
app.use(session({
store: new RedisStore({ client: redisClient, prefix: 'sess:' }),
name: '__Host-sid', // __Host- prefix enforces Secure + no Domain
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
rolling: true, // Reset expiry on each request
cookie: {
secure: true,
httpOnly: true,
sameSite: 'strict',
maxAge: 30 * 60 * 1000, // 30-minute idle timeout
path: '/',
},
}));
// Login handler — regenerate session to prevent fixation
app.post('/login', async (req, res) => {
const user = await authenticate(req.body.email, req.body.password);
if (!user) return res.status(401).json({ error: 'Invalid credentials' });
// Regenerate session ID to prevent session fixation
req.session.regenerate((err) => {
if (err) return res.status(500).json({ error: 'Session error' });
req.session.userId = user.id;
req.session.roles = user.roles;
req.session.createdAt = Date.now();
req.session.save(() => {
res.json({ message: 'Logged in' });
});
});
});
// Logout — destroy session
app.post('/logout', (req, res) => {
req.session.destroy((err) => {
res.clearCookie('__Host-sid');
res.json({ message: 'Logged out' });
});
});
Absolute Timeout Middleware
function enforceAbsoluteTimeout(maxAge = 8 * 60 * 60 * 1000) {
return (req, res, next) => {
if (req.session?.createdAt) {
if (Date.now() - req.session.createdAt > maxAge) {
return req.session.destroy(() => {
res.clearCookie('__Host-sid');
res.status(401).json({ error: 'Session expired' });
});
}
}
next();
};
}
Django Session Configuration
# settings.py
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "sessions"
SESSION_COOKIE_NAME = "__Host-sessionid"
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = "Strict"
SESSION_COOKIE_AGE = 1800 # 30 minutes
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
SESSION_SAVE_EVERY_REQUEST = True # Rolling expiry
CACHES = {
"sessions": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
},
}
}
Session Revocation (Force Logout)
from django.contrib.sessions.backends.cache import SessionStore
def revoke_all_sessions_for_user(user_id: int):
"""Force logout by clearing all sessions for a user.
Requires storing user_id -> session_key mappings."""
session_keys = UserSession.objects.filter(user_id=user_id).values_list('session_key', flat=True)
for key in session_keys:
store = SessionStore(session_key=key)
store.delete()
UserSession.objects.filter(user_id=user_id).delete()
Best Practices
- Generate session IDs with a CSPRNG — never use predictable or sequential identifiers.
- Regenerate the session ID after login and after any privilege elevation to prevent session fixation.
- Set
HttpOnly,Secure,SameSite=Stricton session cookies. Use the__Host-cookie prefix where possible. - Implement both idle and absolute timeouts. Idle: 15–30 minutes. Absolute: 8–12 hours.
- Use an external session store (Redis, Memcached) for production. In-memory stores do not survive restarts and cannot scale horizontally.
- Destroy sessions completely on logout — delete from the store and clear the cookie.
- Bind sessions to client metadata (e.g., User-Agent hash, IP range) as an additional validation signal.
- Maintain a user-to-session mapping so you can revoke all sessions for a user on password change or compromise.
Common Pitfalls
- Not regenerating session ID after authentication: Leaves the application vulnerable to session fixation attacks.
- Using default cookie names: Framework-default names (e.g.,
JSESSIONID,connect.sid) signal the technology stack to attackers. Use custom names. - Storing sensitive data in the session cookie itself: Unless encrypted and integrity-protected, cookie contents can be tampered with.
- No server-side session invalidation on logout: Simply clearing the cookie client-side does not destroy the session on the server.
- Relying only on idle timeout: Without an absolute timeout, a continuously active attacker session never expires.
- In-memory session store in production: Causes session loss on restart and prevents horizontal scaling.
Anti-Patterns
Over-engineering for hypothetical scale. Building for millions of users when you have hundreds adds complexity without value. Solve today's problems first.
Ignoring the existing ecosystem. Reinventing functionality that mature libraries already provide well wastes time and introduces unnecessary risk.
Premature abstraction. Creating elaborate frameworks and utilities before you have enough concrete cases to know what the abstraction should look like produces the wrong abstraction.
Neglecting error handling at boundaries. Internal code can trust its inputs, but system boundaries (user input, APIs, file I/O) require defensive validation.
Skipping documentation for obvious code. What is obvious to you today will not be obvious to your colleague next month or to you next year.
Install this skill directly: skilldb add auth-patterns-skills
Related Skills
API Key Auth
API key generation, hashing, rotation, scoping, and rate limiting patterns
JWT Tokens
JWT creation, validation, refresh token rotation, and secure token storage patterns
Multi Tenancy
Multi-tenant authentication isolation, tenant-scoped tokens, and data boundary enforcement
Oauth2 Flows
OAuth 2.0 authorization code, PKCE, client credentials, and token exchange patterns
Passkeys
Passkeys and WebAuthn implementation for passwordless authentication
Rbac
Role-based access control design, permission hierarchies, and enforcement patterns