Session hijacking is when an attacker takes over a user’s already-authenticated session by stealing the cookie or token that proves the login happened, so they never have to log in themselves. Multi-factor authentication does not stop it, because MFA is checked at the moment of login and a stolen session was created after that check passed. Infostealer malware has made this routine, since it copies session cookies and tokens out of the browser on an infected machine, and the practical defenses are shorter and narrower sessions, tokens tied to a device key, re-authentication for sensitive actions, and the ability to revoke everything quickly.
This post explains how stolen sessions work, which controls shrink the damage, and how to set them up on Keycloak 26.x. Skycloak provides identity management as a service, running Keycloak for you. This post is written for engineers who own the login system of a product, not for incident responders, although the revocation section doubles as a short playbook.
What is session hijacking?
When a user logs in, the server issues something the browser presents on every later request: a session cookie, an access token, a refresh token, or a combination. Whoever holds that artifact is treated as the user until it expires or is revoked. The OWASP Session Management Cheat Sheet describes the session identifier as the thing an attacker wants, because possessing it is equivalent to possessing the authenticated user.
Older hijacking happened over the network, by sniffing unencrypted traffic or injecting script into a page. Those routes still exist, but TLS everywhere and HttpOnly cookies have made them harder, which is part of why attention moved to the endpoint itself.
What are the types of session hijacking?
The same end result, an attacker holding a valid session, can be reached in several ways:
| Type | How the session is obtained |
|---|---|
| Infostealer cookie theft | Malware on the user’s device copies cookies and tokens from the browser |
| Adversary-in-the-middle phishing | A phishing site proxies the real login and captures the session cookie after the user completes MFA |
| Cross-site scripting (XSS) | Injected script reads a token from local storage or a cookie that is not marked HttpOnly |
| Network sniffing (sidejacking) | Traffic on an unencrypted connection is read, which TLS prevents |
| Session fixation | The attacker plants a known session identifier before login and waits for the victim to authenticate with it |
This post concentrates on the first row, because it needs no flaw in your application and bypasses MFA, but the controls further down help against the others as well.
How do infostealers steal sessions?
An infostealer is malware, typically delivered through a cracked installer, a fake software update or a phishing attachment, whose job is to harvest data from the machine it lands on and send it to the attacker. Browsers keep cookies and, in many web apps, tokens in local storage on disk, and a process running as the same user can read them. Common infostealer families collect saved passwords, cookies and autofill data in one sweep.
Once they have the files, the attacker imports the stolen cookies into their own browser, loads the product, and arrives already signed in, with no password prompt and no MFA challenge because the server sees a valid session.
Why doesn’t MFA protect a stolen session?
MFA verifies who is logging in, once. It does not bind the resulting session to the device or person that passed the check. After a successful login the server has no further proof of identity beyond the cookie or token, so if that artifact is copied the copy works as well as the original.
A related consequence is that changing the password does not necessarily end the attacker’s access. Unless the system also invalidates existing sessions and refresh tokens on a password reset, those continue to work. Check what your own system does here before an incident forces the question.
This is not an argument against MFA, which still blocks the large class of attacks that start from a stolen or guessed password. It is an argument for treating session security as a separate layer that needs its own controls. Phishing that captures sessions in transit, such as the attacks described in our post on device code phishing and passkey lures, reaches the same place by a different road.
Which controls limit the damage of a stolen session?
No single setting fixes this, so the list below goes roughly from cheapest to most involved.
Keep access tokens short
An access token is valid until it expires, and a resource server that validates it locally cannot know it was stolen. A short lifetime caps how long a copied access token is useful. Keycloak lets you set the lifespan per realm under Realm settings, Tokens, and per client in the client’s advanced settings.
Rotate refresh tokens and detect reuse
A refresh token is the more valuable target because it mints new access tokens. In Keycloak, enabling Revoke Refresh Token makes Keycloak revoke a refresh token once it has been used (up to the Refresh Token Max Reuse count), so a stolen token that is used after the legitimate client has refreshed is rejected. The Keycloak Server Administration Guide documents the setting, and our refresh token rotation guide covers the reuse window and how it interacts with session timeouts. RFC 9700, the OAuth 2.0 Security Best Current Practice, requires refresh tokens issued to public clients to be either sender-constrained or rotated.
Set idle and maximum session limits
The SSO session idle and SSO session max values in Realm settings, Sessions decide how long a browser session survives. A stolen session cookie is only useful while the session behind it is alive, so an idle timeout of hours rather than weeks, and a hard maximum, both reduce the window. The trade-off is how often legitimate users have to log in again, which is a product decision. We cover the settings in session management from refresh to idle timeouts, and the choice between cookie, token and server-side sessions in this comparison.
Bind tokens to a key with DPoP
Sender-constrained tokens make a stolen token useless without a private key that never leaves the client. DPoP (Demonstrating Proof-of-Possession), specified in RFC 9449, has the client sign each request with its own key, and the server checks the token is bound to that key. Keycloak supports DPoP, fully supported since 26.4, with the dpop feature enabled by default, and a client setting called Require DPoP bound tokens. Our walkthrough of DPoP against the Keycloak Admin API shows the mechanics.
It is important to be clear about what DPoP protects. It protects tokens held by an application against theft and replay, provided the private key is non-extractable (for example a WebCrypto key that cannot be exported); malware running on the same device can still use it in place. It does not protect the Keycloak login session cookie in the user’s browser, because an attacker who holds that cookie can walk through a normal authorization flow and have their own key bound to the new tokens. DPoP therefore reduces the value of tokens stolen from an app, but you still need session limits and revocation for the browser session itself.
Re-authenticate for sensitive actions
Even a legitimate session should not authorize everything indefinitely. Requiring a fresh login or step-up before changing an email address, adding an MFA factor, or creating API credentials stops an attacker with a stolen session from entrenching themselves. In OIDC this is done with the max_age parameter or an authentication context class, and Keycloak can map those to authentication levels.
Watch for signals and revoke fast
Continuous access evaluation, where the identity provider tells apps in near real time that a session has become risky, is the long-term answer for the endpoint problem. Keycloak has experimental support for the Shared Signals Framework and CAEP events, which our post on CAEP and shared signals describes, and the NIST IR 8587 token protection mapping lays out how these controls line up with guidance on protecting tokens.
How do you respond when a session is stolen?
A short sequence works for most SaaS incidents:
- Revoke the user’s sessions and refresh tokens. In the Keycloak admin console, open the user’s Sessions tab and sign out the sessions, or use the Admin REST API. Revoking a single session without logging everyone out is covered in this guide.
- Revoke OAuth grants and offline tokens. Long-lived offline tokens survive normal logouts, so check for them and remove consent grants the attacker may have created.
- Inspect what the attacker changed. Look for new MFA factors, new recovery methods, changed email addresses and newly created API keys, since these let them return after you clear the session.
- Rotate secrets the session could reach. If the user had access to client secrets or admin functions, rotate them.
- Reset the credential and the machine. Resetting the password only helps if the infected device is cleaned first, otherwise the next session is stolen too.
If the stolen session belonged to a realm administrator, treat the realm as exposed and rotate client secrets and signing keys as you would after any admin compromise.
What should you configure on Keycloak today?
A reasonable baseline for a production realm, adjusted to your users’ tolerance for logging in again:
- Access token lifespan of minutes rather than hours.
- Revoke Refresh Token on, with the reuse setting at its default of zero for clients that can handle rotation.
- SSO session idle and max values set deliberately, with shorter values for admin and finance roles.
- DPoP required for confidential and public clients that can implement it, starting with the browser-based and mobile apps your users sign in to.
- Step-up authentication in front of account recovery and credential changes.
- Event logging turned on, so you can see logins from new locations and unusual token refreshes. The session management feature and advanced security feature pages describe what is available in Skycloak.
Frequently asked questions
Does MFA prevent session hijacking?
No. MFA protects the login step, and a hijacked session skips it by reusing a cookie or token created after the login succeeded. Combine MFA with short sessions, refresh token rotation, token binding and re-authentication for sensitive actions.
How do attackers steal session cookies?
The most common route today is infostealer malware, which reads cookies and stored tokens from the browser’s data on an infected computer. Other routes include phishing proxies that capture the session as the user logs in, and cross-site scripting that reads tokens kept in local storage.
Does changing my password log out a hijacked session?
Only if the service invalidates existing sessions and refresh tokens when the password changes. In Keycloak, the password update page offers a “Sign out from other devices” option, and you should also revoke sessions explicitly from the admin console after a suspected compromise.
What is the difference between session hijacking and session fixation?
In hijacking the attacker steals a session identifier that already belongs to a logged-in user. In fixation the attacker plants a known identifier before login and waits for the victim to authenticate with it. Issuing a new session identifier at login is the standard fix for fixation.
Can DPoP stop a stolen browser cookie?
Not by itself. DPoP binds tokens to a client key, which protects tokens stolen from an app. A stolen identity provider session cookie can still be used to obtain new tokens bound to the attacker’s own key, so session limits and fast revocation remain necessary.
How long should a session last?
There is no universal number. A common approach is to make sessions short for high-risk roles such as administrators and longer for low-risk consumer use, and to pair longer sessions with re-authentication for sensitive actions.