SOFTWARE / SYSTEMS / AIEngineering news. Technical depth.
Identity / 4 MIN READ

Prevent Session Fixation at Login and Privilege Transitions

Rotate session identifiers at login, MFA, recovery, impersonation, and privilege changes, carrying forward only explicitly allowlisted anonymous state.

Create a new session identifier whenever authentication or privilege changes. Do not upgrade an attacker-known anonymous session in place. Copy only allowlisted, server-owned continuity state into the new session, invalidate the old identifier, and rotate again after MFA completion, account recovery, impersonation, or privilege elevation.

Understand the adoption attack

In session fixation, the attacker causes a victim to use a session identifier the attacker already knows. If login attaches the victim’s identity to that same identifier, the attacker can reuse it. OWASP’s session fixation description explains the core failure mode: the application does not assign a new session ID on authentication, so an attacker who established or learned the pre-login identifier can hijack the authenticated session. It also covers fixation through URL parameters, form fields, cookies, and script. Strong random identifiers do not help when the attacker chooses or learns the identifier before authentication.

At login completion, create a fresh server-side session with a fresh cookie. Invalidate the pre-login session and reject it on subsequent requests. Set secure cookie attributes such as Secure, HttpOnly, and an appropriate SameSite policy, and scope cookies as narrowly as your application requires. Do not accept session IDs in URLs or request bodies when the cookie is the chosen transport.

OWASP’s Session Management Cheat Sheet explains that the session ID binds authentication to HTTP traffic and access control, and that applications commonly maintain session state both before and after authentication. In practice, rotate the session identifier when authentication or authority changes. Treat entering an administrator mode, completing step-up authentication, switching from recovery to normal access, and starting support impersonation as new security contexts.

Carry state by reference and policy

An anonymous cart can survive login, but copy its server-side cart ID only after verifying ownership rules. Merge rather than overwrite if the account already has a cart, and reprice or reauthorize items. Carry OAuth state only for the protocol transaction that created it and consume it once. Do not copy arbitrary session key-value data, redirect URLs, tenant choices, or feature flags into the authenticated session.

MFA progress is temporary authentication state, not a partially privileged session. Bind it to a short-lived transaction ID, intended identity, allowed next method, attempt limit, and expiry. After successful MFA, consume the transaction and create or rotate the authenticated session. A pre-MFA cookie should not become valid for application APIs merely because one database flag changed.

Prefer an implementation that invalidates the old identifier and creates the new session as one indivisible transition, or otherwise ensures the old identifier cannot become authenticated during races. If two login completions race, choose one active result or create two independently authorized sessions; never leave the anonymous identifier authenticated. Store a session-family or transition ID so operators can trace rotations without logging raw tokens.

Separate Ory deployment choices

Ory Kratos is an API-first identity and user-management system with self-service flows and a custom user-interface option, as described in the Ory Kratos introduction. For teams already using Kratos, we recommend starting from the Ory session overview for the browser or API flow you actually deploy. That documentation explains that browser-based sign-in issues an Ory session cookie, while non-browser clients use a session token. Ory Network provides managed services based on Ory’s open-source projects, and managed-service capabilities should be evaluated separately from self-hosted open-source deployments. Application-owned carts, tenant choices, and redirects still require an explicit carry-over policy.

Test the transitions directly

Start with an attacker-known anonymous cookie, log in as the victim, and prove the old cookie remains unauthenticated. Repeat for password login, social login callback, MFA, recovery, role elevation, tenant-admin mode, and impersonation. Test two tabs using the old and new cookies, logout during rotation, and a stale request arriving after invalidation.

Monitor rotations, rejected retired identifiers, simultaneous sessions, and privilege transitions without storing token values. Keep absolute and idle expiry independent of rotation; changing an identifier should not accidentally extend a session beyond policy.

Preserve CSRF protections across rotation. A fresh authenticated session should receive a fresh CSRF secret or a securely rebound one, and outstanding forms from the anonymous context should fail safely. Otherwise, carrying a pre-login anti-CSRF value can accidentally bind attacker-influenced state to the new authority.

The next step is to enumerate every transition that increases authority and add a test asserting both a new identifier and rejection of the old one. Review after session architecture changes.

SOURCES & REVIEW

Sources are linked throughout this guide. Product capabilities can change; consult the linked documentation for your deployment.

Read our editorial approach ↗