1

Concept

Session Creation

A session should come into existence at a clearly defined point in the application's lifecycle.

An application may create an anonymous, pre-authentication session when a user first visits. This can be useful for maintaining state such as:

CSRF tokens
Shopping carts
Multi-step forms
Temporary preferences

The more security-critical transition happens when the user successfully authenticates.

At that point, the application should not simply upgrade the existing session ID into an authenticated session.

Before login:

Session ID: anonymous_123
        ↓
User submits valid credentials
        ↓
❌ Keep anonymous_123 and mark it authenticated

Instead:

Before login:

Session ID: anonymous_123
        ↓
User successfully authenticates
        ↓
Invalidate / regenerate session ID
        ↓
Create:
Session ID: authenticated_987

Any state that legitimately needs to survive authentication, such as a shopping cart, should be migrated to the new session rather than preserving the old session identifier.

This directly prevents session fixation. Even if an attacker knew or influenced the pre-authentication session ID, that ID becomes useless once authentication generates a fresh credential.

The second design decision is deciding what information should actually live inside the session.

A session generally needs enough information to identify the authenticated user:

session
β†’ user_id
β†’ authentication state
β†’ session metadata

But storing large amounts of authorization data can create a staleness problem:

User logs in
        ↓
Session stores:

role = admin
permissions = [...]
        ↓
Administrator removes user's privileges
        ↓
Old session still contains:

role = admin
permissions = [...]

If the application trusts those cached values without rechecking the current authorization state, the user may retain permissions they should no longer have.

For sensitive or frequently changing permissions, it is often safer to derive authorization from a current trusted source rather than treating data calculated at login as permanently valid.

The principle is:

Session
β†’ establishes who the user is

Authorization
β†’ determines what that user may do now

Those decisions should not become permanently coupled just because the user authenticated earlier.

2

Concept

Session Rotation

Session rotation means issuing a new session ID to replace an existing one while preserving the session's legitimate underlying state. The user remains logged in, but the credential identifying that session changes.

Old session ID:  abc123
        ↓
Session rotation
        ↓
New session ID:  xyz789
        ↓
Old ID becomes invalid

The most important use of rotation occurs immediately after authentication, where it prevents session fixation. But the same principle applies at other important trust boundaries.

Examples include:

Successful login
        ↓
Rotate session ID

Privilege change
        ↓
Rotate session ID

Switching between accounts
        ↓
Rotate session ID

Password change
        ↓
Rotate session ID

For genuinely sensitive applications, session IDs may also be rotated periodically during a long-lived session.

The security benefit is easiest to see in a session-hijacking scenario:

Attacker captures:

Session ID: abc123
        ↓
Application rotates session
        ↓
New ID: xyz789
        ↓
abc123 becomes invalid
        ↓
Attacker's captured credential
no longer works

Rotation therefore limits how long a particular session identifier remains useful.

Without rotation:

Captured session ID
        ↓
May remain valid for hours,
days, or the entire session lifetime

With rotation:

Captured session ID
        ↓
Valid only until the next
rotation or invalidation event

This is especially valuable at privilege boundaries. If a user moves from a lower-privilege context to a higher-privilege one, the application should not continue using the same session credential that existed before the privilege change.

3

Concept

Session Expiration

Session Expiration

Every session needs a clearly defined end. Two distinct expiration mechanisms should usually be used together rather than treating them as alternatives: idle expiration and absolute expiration.

Idle Expiration:

Idle, or inactivity, expiration ends a session after a defined period with no activity.

For example:

User logs in
        ↓
Uses application
        ↓
Stops interacting
        ↓
15–30 minutes pass
        ↓
Session expires

The exact timeout depends on the application's sensitivity. A general application might allow 15–30 minutes of inactivity, while an administrative panel or application handling sensitive data may require a shorter timeout.

This protects against a common real-world scenario:

User logs in
        ↓
Walks away from an unlocked device
        ↓
Session remains active indefinitely
        ↓
Someone else uses the existing session

With idle expiration, the abandoned session eventually becomes invalid even if the user never explicitly logs out.

Absolute Expiration:

Absolute expiration ends a session after a fixed maximum lifetime regardless of activity.

For example:

Session created at 09:00
        ↓
User remains continuously active
        ↓
Absolute limit: 8 hours
        ↓
17:00 β†’ session expires

Even constant activity does not extend the session beyond its maximum lifetime.

This limits the lifetime of an undetected session hijack:

Attacker obtains session ID
        ↓
Keeps using the session
        ↓
Idle timeout never triggers
        ↓
Absolute expiration reached
        ↓
Session becomes invalid
        ↓
Re-authentication required

Using both Expiration provides protection against each scenario:

No activity
        ↓
Idle expiration
        ↓
Session ends


Continuous activity
        ↓
Absolute expiration
        ↓
Maximum session lifetime reached
        ↓
Session ends

Both limits should be enforced by the server-side session mechanism, not merely by deleting the cookie or hiding the logged-in interface on the client. A stolen session credential must be rejected after expiration even if an attacker manually preserves or resends it.

4

Concept

Logout

Logout needs to be a real server-side event, not just a client-side redirect to the login page.

When the user clicks Log out, the application should invalidate the authenticated session itself:

User clicks "Log out"
        ↓
Browser sends logout request
        ↓
Server invalidates the session
        ↓
Session ID becomes unusable
        ↓
Browser clears its local cookie

For a stateful session, this means destroying or invalidating the session record stored on the server.

For example:

Before logout:

Session ID: abc123
        ↓
Server session store:

abc123 β†’ user_id: 4521

After logout:

Session ID: abc123
        ↓
Server session store:

abc123 β†’ invalid / deleted

Simply deleting the cookie in the victim's browser is not enough:

Browser deletes:

session=abc123
        ↓
But server still accepts:

session=abc123

If someone captured that session ID beforehand, they can continue replaying it even though the legitimate user believes they have logged out.

The same principle applies to token-based authentication. If immediate invalidation is required, the application needs a server-side revocation mechanism, such as a denylist or another design that allows the token to be rejected before its normal expiration.

Logout Scope

It's also important to define what logout actually means for the application.

Current-device logout
β†’ Invalidates only the session being used

Log out of all devices
β†’ Invalidates every active session belonging to the account

Neither approach is automatically correct for every application.

A typical application may reasonably make ordinary logout affect only the current session:

Laptop session     β†’ invalidated
Phone session      β†’ remains active
Tablet session     β†’ remains active

But users should ideally have an explicit option for:

Log out of all devices

This becomes especially important after a suspected compromise or password change.

The principle is:

Client-side cookie deletion
β†’ removes the browser's copy

Server-side invalidation
β†’ makes the credential itself unusable
5

Concept

Session Invalidation

This is the broader category covering situations where a session needs to be forcibly ended by the server, independent of whether the user chooses to log out.

Unlike normal logout, which is initiated by the user, forced invalidation is triggered by security events elsewhere in the application.

The important triggers should be handled explicitly:

Password changed
        ↓
Invalidate other active sessions

Account locked or suspended
        ↓
Invalidate active sessions

Account flagged as compromised
        ↓
Immediately terminate active sessions

Administrator revokes access
        ↓
Existing sessions must no longer retain access

Consider a password compromise:

Attacker steals password
        ↓
Attacker logs in
        ↓
Attacker now has:

Session ID: attacker_session

The legitimate user notices the compromise and changes their password:

Password changed
        ↓
❌ Attacker's existing session remains valid
        ↓
Attacker still has access

Changing the password alone does not necessarily remove an attacker who already has a valid session.

The correct response is:

Password changed
        ↓
Invalidate existing sessions
        ↓
Old session IDs become unusable
        ↓
Require affected devices to authenticate again

The same principle applies when an account is locked, suspended, disabled, or flagged as compromised. The application should not wait for existing sessions to expire naturally.

Account suspended
        ↓
Server invalidates active sessions immediately
        ↓
Previously issued session IDs are rejected

This invalidation needs to happen at the actual authority that validates the sessionβ€”typically the server-side session store or a token revocation mechanism.

Browser deletes cookie
        ↓
❌ One client no longer has the token


Server invalidates session
        ↓
βœ… Token itself is no longer accepted

Taken as a whole, the session lifecycleβ€”from creation through rotation, expiration, logout, and forced invalidationβ€”is one continuous security principle:

Create
   ↓
Rotate at trust boundaries
   ↓
Expire after inactivity
   +
Expire after maximum lifetime
   ↓
Invalidate on logout
   ↓
Force invalidation after security events