Revoke One Keycloak Session Without Logging the User Out Everywhere

Guilliano Molaire Guilliano Molaire 9 min read

Last updated: July 2026

Keycloak does not have a one-click “revoke just this session” button in the UI for administrators, but you have two reliable programmatic options. To end a single session, either delete that specific user session by ID via the Admin REST API (DELETE /admin/realms/{realm}/sessions/{sessionId}), or have the client call the OIDC logout endpoint with its refresh_token to end only the session tied to that token. The OAuth token revocation endpoint (/protocol/openid-connect/revoke, defined in RFC 7009) has behaved inconsistently for refresh tokens across Keycloak versions — always verify its behavior against your specific deployment before relying on it in production.

This question has surfaced repeatedly across the Keycloak community, including GitHub discussions #27815 and issue #35486. The confusion is understandable: Keycloak’s session model is layered, the available endpoints do subtly different things, and the revocation endpoint’s behavior has changed between versions. This post walks through each option with exact endpoints and curl examples so you can pick the right approach for your situation.

Understanding Keycloak’s Session Model

Before choosing a revocation strategy, it helps to understand what you are actually revoking.

In Keycloak, a user session (UserSessionModel) is created when a user authenticates against a realm. It represents the user’s login state and has a unique session ID. Each user session can have multiple client sessions nested inside it — one per client (application) the user has accessed. The access token and refresh token your application holds are both tied to a specific client session, which belongs to a specific user session.

This means:

  • A user who is logged into your web app, mobile app, and admin dashboard simultaneously has three client sessions potentially spanning one or more user sessions (depending on SSO behavior and how sessions are shared across clients).
  • Revoking a user session ends all client sessions within it, immediately invalidating all tokens associated with that session.
  • Revoking a client session ends only that application’s access, leaving the user still authenticated to other clients.
  • An access token that has already been issued is valid until it expires, regardless of session revocation — unless your resource servers perform active introspection on every request.

Keep this model in mind as you evaluate the options below. For a deeper look at token lifetimes and what happens after a session ends, see the Skycloak post on JWT token lifecycle management, expiration, refresh, and revocation strategies.

Option 1 — Admin REST API: Delete One Session by ID

This is the most precise, server-authoritative approach. You look up the user’s session IDs, pick the one you want to end, and delete it. The user stays logged in on all other sessions.

Step 1 — Get an Admin Access Token

You need a bearer token with realm admin privileges. The cleanest way in automation is a service account:

ADMIN_TOKEN=$(curl -s -X POST 
  "https://keycloak.example.com/realms/master/protocol/openid-connect/token" 
  -H "Content-Type: application/x-www-form-urlencoded" 
  -d "grant_type=client_credentials" 
  -d "client_id=admin-cli" 
  -d "client_secret=YOUR_CLIENT_SECRET" 
  | jq -r '.access_token')

Replace master with your realm if you have a dedicated admin realm. For production, prefer a dedicated service account with only the permissions it needs rather than using the admin-cli client directly.

Step 2 — List the User’s Sessions

Find the user ID first, then list their sessions:

# Find user ID by username
USER_ID=$(curl -s 
  "https://keycloak.example.com/admin/realms/myrealm/users?username=alice&exact=true" 
  -H "Authorization: Bearer $ADMIN_TOKEN" 
  | jq -r '.[0].id')

# List all sessions for that user
curl -s 
  "https://keycloak.example.com/admin/realms/myrealm/users/$USER_ID/sessions" 
  -H "Authorization: Bearer $ADMIN_TOKEN" 
  | jq '[.[] | {id, ipAddress, started, lastAccess, clients: (.clients | keys)}]'

The response is an array of user session objects. Each has an id (the session ID), ipAddress, started and lastAccess timestamps, and a clients map showing which client IDs have client sessions within it. This lets you identify which session belongs to which device or client application.

Step 3 — Delete the Target Session

SESSION_ID="the-session-id-you-want-to-remove"

curl -s -X DELETE 
  "https://keycloak.example.com/admin/realms/myrealm/sessions/$SESSION_ID" 
  -H "Authorization: Bearer $ADMIN_TOKEN" 
  -w "nHTTP Status: %{http_code}n"

A 204 No Content response means the session was deleted. The user is now logged out of all clients that shared that session, but any other session IDs remain valid.

This endpoint is available in Keycloak 26.x at DELETE /admin/realms/{realm}/sessions/{sessionId} and has been stable across recent major versions. It requires the manage-users role (or realm-admin) on the target realm.

Option 2 — OIDC Logout Endpoint with the Refresh Token

If the goal is for a client application to log itself out without affecting the user’s other sessions, the OIDC logout endpoint is the right tool. The client sends its own refresh token, and Keycloak ends the client session associated with that token — leaving the user’s other client sessions intact.

curl -s -X POST 
  "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/logout" 
  -H "Content-Type: application/x-www-form-urlencoded" 
  -d "client_id=my-app" 
  -d "client_secret=MY_APP_SECRET" 
  -d "refresh_token=THE_REFRESH_TOKEN_TO_REVOKE"

A 204 No Content response indicates success. The refresh token (and the access token associated with that client session) is now invalid. The user remains authenticated in any other clients or sessions.

This approach is client-initiated rather than admin-initiated, which is appropriate when:

  • Your application is handling its own “log out of this device” feature.
  • You want to invalidate the session as part of a token rotation failure or security event at the application layer.
  • You don’t have or want to grant admin API access to the application.

For background on how refresh token rotation interacts with session state, see our guide on Keycloak refresh token rotation.

What Happens to the Access Token?

Neither the admin delete nor the logout endpoint immediately invalidates access tokens that have already been issued. An access token is a signed, self-contained JWT. Once issued, it is valid until its exp claim is reached — unless your resource servers call the Keycloak introspection endpoint (/protocol/openid-connect/token/introspect) on every request to check whether the underlying session is still active.

If short access token lifetimes (60-300 seconds) are not acceptable and you need immediate revocation, enable token introspection on your resource servers. This trades latency for revocation precision. See Keycloak session timeout configuration for guidance on tuning these lifetimes.

Option 3 — The Revocation Endpoint and Why It Is Unreliable

Keycloak implements the OAuth 2.0 Token Revocation endpoint (RFC 7009) at /realms/{realm}/protocol/openid-connect/revoke. In theory, posting a refresh token here should invalidate it.

curl -s -X POST 
  "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/revoke" 
  -H "Content-Type: application/x-www-form-urlencoded" 
  -d "client_id=my-app" 
  -d "client_secret=MY_APP_SECRET" 
  -d "token=THE_REFRESH_TOKEN" 
  -d "token_type_hint=refresh_token"

The endpoint returns 200 OK regardless of whether the token was actually revoked (this is per-spec for RFC 7009 — the spec says not to leak token validity information). The problem is that Keycloak’s behavior here has been inconsistent:

  • In some versions, revoking a refresh token only marks it as revoked without ending the underlying user session. The user can still silently obtain a new token via the session cookie on their next visit.
  • In others, the underlying user session is also terminated.
  • For offline tokens specifically, revocation behavior has had documented bugs across Keycloak versions. An offline token is not tied to a user session in the same way as a regular refresh token, so revocation semantics differ. See our Keycloak offline tokens explained post for the details.

The bottom line: if you need guaranteed revocation of a single session, use Option 1 (admin delete by session ID) or Option 2 (logout endpoint with refresh token). Do not rely solely on the revocation endpoint without first verifying its behavior on your specific Keycloak version in a test environment.

Option 4 — Logout All Sessions (and Why You Usually Don’t Want It)

For completeness, here are the “nuclear” options that end all of a user’s sessions simultaneously.

Admin REST API — Logout All

curl -s -X POST 
  "https://keycloak.example.com/admin/realms/myrealm/users/$USER_ID/logout" 
  -H "Authorization: Bearer $ADMIN_TOKEN" 
  -w "nHTTP Status: %{http_code}n"

This terminates every active session for the user across all clients. Use this for account compromise scenarios, not routine single-device logout.

Not-Before Revocation Policy

In the Keycloak Admin Console under Realm Settings > Sessions > Not before, you can set a timestamp. Keycloak will reject any token issued before that timestamp when a client checks in (requires client adapters or introspection). This is a realm-wide or user-level policy — not targeted at a single session — and requires cooperating clients to enforce it.

For troubleshooting expired or rejected tokens in general, see Keycloak token expired troubleshooting.

Endpoint Summary

Method Endpoint Initiator Scope Reliable?
Admin delete session DELETE /admin/realms/{realm}/sessions/{id} Admin/backend One user session Yes
OIDC logout with refresh token POST /realms/{realm}/protocol/openid-connect/logout Client app One client session Yes
Token revocation (RFC 7009) POST /realms/{realm}/protocol/openid-connect/revoke Client app One token (session behavior varies) Verify on your version
Admin logout-all POST /admin/realms/{realm}/users/{id}/logout Admin/backend All sessions for user Yes
Not-before policy Admin Console > Realm Settings Admin All sessions before timestamp Requires cooperating clients

A Note on Version Differences

The Admin REST API session endpoints and the OIDC logout endpoint have been stable across Keycloak 21 through 26.x. The revocation endpoint’s behavior — particularly around whether it terminates the user session or only invalidates the token — has changed between minor versions. Keycloak 26.x uses Quarkus as its runtime (WildFly was removed in Keycloak 17); none of the endpoints described here are WildFly-specific, but if you are running an old WildFly-based deployment, the Admin API base path differs (/auth/admin/realms/ vs /admin/realms/).

Always test revocation behavior in a staging environment before deploying to production. The Keycloak GitHub issue tracker is the authoritative record of known bugs; issues #27815 and #35486 are good starting points if your version shows unexpected behavior.

Frequently Asked Questions

How do I log out a single Keycloak session?

The most reliable way is to call DELETE /admin/realms/{realm}/sessions/{sessionId} with an admin bearer token. First, retrieve the user’s session list via GET /admin/realms/{realm}/users/{userId}/sessions to get the session ID you want to remove. This ends that one session and all client sessions within it, without affecting the user’s other active sessions.

How do I revoke one refresh token in Keycloak?

Have the client application call the OIDC logout endpoint: POST /realms/{realm}/protocol/openid-connect/logout with client_id, client_secret, and refresh_token in the request body. Keycloak will end the client session associated with that refresh token. The user’s other sessions remain active. Avoid relying on the RFC 7009 revocation endpoint alone, as its session-termination behavior has been inconsistent across Keycloak versions.

How do I end all of a user’s sessions?

Call POST /admin/realms/{realm}/users/{userId}/logout with an admin bearer token. This terminates all active sessions for that user across every client in the realm. It is the right choice for an account compromise response but too broad for routine single-device logout flows.

Will revoking a session immediately invalidate the access token?

Not automatically. Access tokens are self-contained JWTs that remain valid until their exp claim expires. To enforce immediate invalidation, your resource servers must call the Keycloak introspection endpoint on each request rather than relying solely on JWT signature verification. Keeping access token lifetimes short (60-300 seconds) limits the window of risk without requiring introspection on every call.

Does the RFC 7009 revocation endpoint work reliably in Keycloak?

It depends on the version and token type. For regular refresh tokens in recent Keycloak versions, it generally marks the token as revoked, but whether it also terminates the underlying user session varies. For offline refresh tokens, revocation behavior has had documented inconsistencies. Always test on your specific version. For guaranteed single-session revocation, use the Admin API delete or the OIDC logout endpoint instead.

Conclusion

Revoking a single Keycloak session without logging the user out everywhere comes down to two reliable options: the Admin REST API’s DELETE /admin/realms/{realm}/sessions/{sessionId} for server-side session deletion, and the OIDC logout endpoint with a refresh_token body parameter for client-initiated single-session logout. The revocation endpoint exists but has enough version-to-version inconsistency that it should not be your first choice without explicit testing.

Key takeaways:

  • Keycloak users have one or more user sessions, each containing client sessions. Know which layer you are targeting.
  • Access tokens remain valid until expiry regardless of session revocation. Use short lifetimes or introspection to close this window.
  • The Admin API delete is the most reliable programmatic option for server-side workflows.
  • The OIDC logout endpoint with refresh_token is the right choice for client-side “log out of this device” flows.
  • Always verify revocation endpoint behavior on your exact Keycloak version.

If managing these session and token configurations sounds like something you would rather not own yourself, Skycloak’s managed Keycloak service handles upgrades, configuration best practices, and session management infrastructure — so your team can focus on your application instead of your identity server.

Tired of running Keycloak yourself?

Skycloak runs real upstream Keycloak for you with a 99.99% SLA. No fork, no lock-in, just managed Keycloak that stays patched and on call so you don't have to.

Guilliano Molaire
Written by
Founder

Guilliano is the founder of Skycloak and a cloud infrastructure specialist with deep expertise in product development and scaling SaaS products. He discovered Keycloak while consulting on enterprise IAM and built Skycloak to make managed Keycloak accessible to teams of every size.

Start Free Trial Talk to Sales
© 2026 Skycloak. All Rights Reserved. Design by Yasser Soliman