Today’s Lesson
Security for Legal SaaS — Episode 19: Session Management
The Invisible Security Layer
Every interaction a user has with your legal SaaS platform happens within a session. The session is the container that holds authentication state, tracks activity, and enforces timeout policies. OWASP’s Session Management Cheat Sheet identifies it as one of the most critical security components — because a compromised session is a compromised user, no credentials required.
Key stat: Verizon’s 2024 DBIR reports that stolen session tokens are increasingly replacing stolen passwords as the primary credential type in breaches — because session tokens bypass MFA entirely. An attacker with a valid session cookie is already authenticated.
For legal SaaS handling privileged attorney-client communications, session management is not a checkbox feature — it’s the mechanism that determines who has access to what, for how long, and under what conditions that access can be revoked.
Session ID Generation — Cryptographic Randomness
The session identifier is a bearer token. Anyone who possesses it has the user’s access. Generation requirements are non-negotiable:
| Requirement | Specification | Rationale |
|---|---|---|
| Entropy | Minimum 128 bits (16 bytes) | OWASP requires ≥128 bits to resist brute-force |
| Randomness source | CSPRNG only | crypto.randomBytes() (Node), os.urandom() (Python), SecureRandom (Java) |
| Format | Opaque, no embedded data | Session IDs must reveal nothing about the user or server state |
| Uniqueness | Globally unique across all active sessions | Collision = session hijacking |
Never use: sequential integers (session_id=1, 2, 3... — trivially enumerable), timestamps or user IDs encoded in the session token, Math.random() or any non-cryptographic PRNG, or UUIDs from non-cryptographic generators (UUID v1 is time-based and predictable).
RFC 4086 (Randomness Requirements for Security) defines the entropy requirements. In practice: use your framework’s built-in session management — Express.js express-session, Django sessions, Rails ActionDispatch::Session — they all use CSPRNGs by default.
Session Storage — Cookie Security Attributes
Sessions should be transported via cookies with strict security attributes. The Cookie specification (RFC 6265bis) defines the attributes; OWASP maps them to security requirements.
| Attribute | Value | Purpose |
|---|---|---|
HttpOnly | true | Prevents JavaScript access — mitigates XSS session theft |
Secure | true | Cookie only sent over HTTPS — prevents network interception |
SameSite | Strict or Lax | Prevents CSRF by limiting cross-origin cookie transmission |
Path | / (or narrowest applicable) | Limits which URL paths receive the cookie |
Domain | Explicit, narrow | Never set to a parent domain that includes other services |
Max-Age / Expires | Match session timeout policy | Browser discards cookie on expiry |
Critical: SameSite=None (required for cross-site cookies) also requires Secure=true. If you need cross-origin session cookies (e.g., embedding your legal SaaS in a client’s iframe), you must use SameSite=None; Secure — but understand this re-opens CSRF vectors. Prefer same-origin architectures for legal SaaS. Google’s SameSite documentation explains the interaction.
Why Not localStorage?
| Storage | XSS Resistant | CSRF Resistant | Sent Automatically |
|---|---|---|---|
| httpOnly Cookie | Yes (JS can’t read) | Needs SameSite | Yes (by browser) |
| localStorage | No (any JS can read) | Yes (not sent auto) | No (must attach manually) |
| sessionStorage | No (any JS can read) | Yes (not sent auto) | No (must attach manually) |
For legal SaaS: httpOnly cookies. Always. OWASP explicitly recommends against localStorage for session tokens.
Session Lifecycle
Creation
On successful authentication: generate a new session ID (128+ bits, CSPRNG), store the session record server-side (user ID, creation time, IP, user agent), set the cookie with all security attributes, and log the authentication event.
Renewal (Re-keying)
Session fixation attacks exploit pre-authentication session IDs. The defence: regenerate the session ID on every privilege change.
| Event | Action |
|---|---|
| Successful login | New session ID (mandatory) |
| Privilege escalation (e.g., entering admin panel) | New session ID |
| Password change | New session ID + invalidate all other sessions |
| Sensitive operation (e.g., document export) | Consider re-authentication |
The old session ID must be immediately invalidated. CWE-384 (Session Fixation) documents the vulnerability class.
Invalidation (Logout)
A secure logout must: delete the server-side session record, clear the session cookie (set empty value + Max-Age=0), invalidate any associated refresh tokens, and log the event.
Common mistake: Only clearing the cookie client-side without deleting the server record. The session ID remains valid — an attacker who captured it earlier can still use it.
Timeout Policies
| Timeout Type | Recommended Value | Purpose |
|---|---|---|
| Idle timeout | 15–30 minutes | Invalidate if no activity (legal SaaS: lean toward 15 min) |
| Absolute timeout | 8–12 hours | Maximum session duration regardless of activity |
| Renewal interval | Every 15 minutes | Rotate session ID periodically even during active use |
NIST SP 800-63B requires re-authentication after 30 minutes of inactivity for AAL2 (Authenticator Assurance Level 2 — the level appropriate for legal SaaS handling privileged content). For AAL3, the idle timeout drops to 15 minutes.
Concurrent Session Policies
| Policy | Use Case | Implementation |
|---|---|---|
| Unlimited concurrent | Low-risk apps, consumer products | Default — no special handling |
| Notify on new session | Medium risk — alert but don’t block | Push notification/email on new login |
| Limit to N sessions | Shared accounts, compliance | Track active sessions; oldest killed when N+1 created |
| Single session only | High security, billing/licensing | New login invalidates all previous sessions |
For legal SaaS, notify + optional terminate is typically appropriate. A partner logging in from their office desktop should be alerted if someone simultaneously logs in from an unfamiliar location — but not automatically kicked out of their existing session, which might be mid-document review.
Google’s security model shows the gold standard: users can view all active sessions (device, location, last activity) and selectively terminate any of them.
Session Fixation
Attack Scenario:
1. Attacker visits your login page and receives a session cookie: session_id=abc123
2. Attacker tricks the victim into using this session ID (via a crafted URL, injected cookie, or XSS)
3. Victim authenticates — the server promotes session_id=abc123 to an authenticated session
4. Attacker uses session_id=abc123 — now authenticated as the victim
Defence: Regenerate the session ID immediately after successful authentication. The pre-auth session ID (abc123) is destroyed; a new ID is issued. The attacker’s copy of abc123 is now invalid.
OWASP Testing Guide v4.2 provides detailed testing procedures.
Session Hijacking Defences
Session hijacking occurs when an attacker obtains a valid session ID through network interception (mitigated by Secure flag + HSTS), XSS (mitigated by HttpOnly flag), malware/browser extension access, or physical access to an unlocked device.
Defence-in-Depth
| Layer | Control |
|---|---|
| Transport | HTTPS everywhere + HSTS preload |
| Cookie attributes | HttpOnly + Secure + SameSite=Strict |
| Binding | Validate client IP range on each request (warn, don’t block — mobile users change IPs) |
| Fingerprinting | User-agent consistency check |
| Anomaly detection | Alert on geographic impossibility (login from Singapore, then London 10 minutes later) |
| Re-authentication | Require password/MFA for sensitive operations regardless of session state |
The MITRE ATT&CK framework documents session hijacking techniques (T1550.004: Use Alternate Authentication Material: Web Session Cookie). Understanding attacker methodology informs defensive architecture.
Server-Side Session Storage
| Store | Pros | Cons |
|---|---|---|
| In-memory (e.g., Node process) | Fast, simple | Lost on restart, no horizontal scaling |
| Redis | Fast, TTL native, pub/sub for invalidation | Additional infrastructure |
| PostgreSQL/MySQL | Durable, queryable, existing infra | Slower than Redis for high-frequency reads |
| Encrypted cookie (client-side) | No server state | Size limits, can’t revoke, sensitive data exposure risk |
For legal SaaS at scale: Redis with PostgreSQL fallback. Redis handles the hot path (session lookup on every request). PostgreSQL provides durability and queryability (audit trails, session history, compliance reporting). Redis documentation on session management covers TTL-based expiry and key patterns.
Legal SaaS-Specific Requirements
1. Matter-level session context — When a lawyer switches between matters, consider whether the session should carry permissions for all matters simultaneously or require explicit context switching (principle of least privilege).
2. Shared workstation awareness — Court computers, law library terminals. Absolute timeout of 30 minutes maximum. Prompt for re-authentication on return from idle.
3. Regulatory compliance — Singapore’s Technology Risk Management Guidelines (MAS TRM) require session timeout policies, concurrent session controls, and session activity logging for regulated financial services — and legal SaaS handling financial litigation data may fall within scope.
4. Privileged operation gating — Downloading case files, exporting client data, changing security settings — require step-up authentication (re-enter password or MFA) regardless of session age.
Implementation Guidance
Recommended configuration: ID length: 32 bytes (256 bits) via crypto.randomBytes. Store: Redis with 30-minute TTL. Cookie: httpOnly=true, secure=true, sameSite='strict'. Regenerate on: login, privilege change, every 15 min. Absolute max: 8 hours. Concurrent limit: 5 sessions per user (notify on 3+). The express-session documentation covers configuration options; use connect-redis as the store adapter.
Conclusion
Session management is where authentication theory meets runtime reality. Generate session IDs with cryptographic randomness. Store them in httpOnly, Secure, SameSite cookies. Regenerate on every privilege change. Enforce idle and absolute timeouts. Support concurrent session visibility and selective termination. And gate sensitive operations behind step-up authentication regardless of session state.
For legal SaaS, the session is the trust boundary between “authenticated user” and “access to privileged communications.” Every weakness in session management is a direct path to privilege breach.
Next episode: OAuth 2.0 and OpenID Connect — delegated authentication, letting users log in with their firm’s identity provider instead of maintaining separate credentials.