Yes. Keycloak impersonation is built in, so you can impersonate a user without any plugin. An administrator with the right permissions opens a user in the Admin Console, chooses Impersonate, and is signed in as that user. The Keycloak admin guide’s own example (opens in a new tab) is support work: reproducing a bug a user reports.
Starting a session is the easy part. The harder questions are who may impersonate whom, what gets recorded, and when access ends. This guide covers the native Keycloak impersonation flow, the impersonation role, fine-grained admin permissions, token exchange, the events Keycloak records, and what your application still owns.
How does Keycloak impersonation work?
Keycloak impersonation is an Admin Console action (opens in a new tab) backed by an Admin REST endpoint.
- Open Users, select the user, and choose Impersonate from the Actions list.
- If the admin and the user are in the same realm, Keycloak logs the admin out and signs them in as the user. From a different realm, such as
master, the admin stays signed in and is also signed in as the user. - Keycloak opens the impersonated user’s Account Console.
The console calls POST /admin/realms/{realm}/users/{id}/impersonation. According to the endpoint’s 26.8.0 code (opens in a new tab), it refuses disabled users and service accounts, creates an ordinary user session, stores the impersonator’s ID and username on it as session notes, and sets the login cookie. Your applications in that realm can then pick up the session through normal single sign-on.
Impersonation is a Keycloak server feature (opens in a new tab) that is on by default. If you don’t want it at all, build Keycloak with --features-disabled="impersonation".
Who can impersonate users in Keycloak?
Anyone with the impersonation role of the realm’s realm-management client can impersonate every user (opens in a new tab) in that realm. Realm administrators with the realm-admin role have full access to the realm, too.
That is fine for two or three trusted engineers. It is too broad for a support team, and there is a catch if you try to narrow it later: when an administrator holds an admin role, Keycloak skips fine-grained permission evaluation (opens in a new tab) and grants access. Remove the impersonation role before relying on permissions.
How do you restrict who can impersonate whom?
Use fine-grained admin permissions version 2 (FGAP v2), which became a supported feature in Keycloak 26.2 (opens in a new tab). FGAP is policy-based access control for administration: you grant specific operations, called scopes, on specific users, groups or clients.
As the fine-grained permissions docs (opens in a new tab) describe, turn it on per realm under Realm settings, Admin Permissions, then create permissions:
| Goal | FGAP v2 configuration |
|---|---|
| Help desk impersonates members of one group | Group permission with impersonate-members on that group, with a group policy for the help desk group |
| Protect specific users, such as admins | User permission for those users with a policy that evaluates to deny |
| Let a role impersonate any user | User permission for all users with impersonate, plus a role policy |
| Let delegated admins find users first | view (or view-members) as well, plus the query-users role to reach the Users section |
Three details matter. Scopes are independent, so impersonate doesn’t imply view. impersonate-members cascades to subgroups, and a deny on a parent group applies to its descendants unless a child group has its own explicit allow. And FGAP is enforced only for the Admin Console and Admin API.
The older FGAP v1 is deprecated and only runs if you start the server with --features=admin-fine-grained-authz:v1.
Can a Keycloak admin impersonate only their own users?
Not with a single generic rule. A long-standing Keycloak discussion (opens in a new tab) asks exactly this: admins impersonate anyone except other admins, while each service provider impersonates only users in its own group. The author found that a v1 policy saw either the impersonator or the target, never both, so it couldn’t check that they shared a group. The question has no answer.
With FGAP v2, the documented route is per group (opens in a new tab): one impersonate-members permission for each customer group, with a policy naming that customer’s support staff. That works when tenants map neatly to groups. Every new tenant then needs its own permission, and nothing in it knows about tickets or temporary assignments.
If “own users” means accounts assigned to an agent this week, or customers on an open ticket, make that check in your application before any session starts. The support permission hierarchy guide covers the policy model, and limiting impersonation to assigned customers covers the check itself.
What about Keycloak token exchange impersonation?
Token exchange is not the same as the Admin Console action, and Keycloak’s token exchange docs (opens in a new tab) show that only the deprecated version supports impersonation.
| Mechanism | Status | Impersonation |
|---|---|---|
| Standard token exchange (V2) | Supported, on by default | Subject impersonation not implemented |
| Legacy token exchange (V1) | Preview and deprecated, off by default, needs FGAP v1 | requested_subject swaps in another user; “direct naked impersonation” needs no subject token |
| Token exchange delegation | Preview, off by default | Not impersonation: the user consents and the token names the actor |
Keycloak warns that if a client allowed direct naked impersonation has its credentials stolen, that client can impersonate any user in the system.
Delegation is newer. It was experimental in Keycloak 26.7.0 and, per the Keycloak 26.8.0 release notes (opens in a new tab), became a preview in 26.8.0. In the delegation flow Keycloak documents (opens in a new tab), a user signs in through a client that requests delegation:user:<admin>, Keycloak checks that the admin has the FGAP v2 delegate permission, and the user approves on a consent screen. The admin then exchanges the user’s token and their own for a token carrying an act claim. Consent is never stored permanently, and the delegated token comes without a refresh token. It is the closest Keycloak gets to customer-approved access, but the customer has to be present to sign in and approve.
How do you audit Keycloak impersonation?
Each impersonation records an IMPERSONATE user event with the impersonator’s username and realm, as the impersonation endpoint code (opens in a new tab) shows. Keycloak doesn’t store user events by default (opens in a new tab), so turn on Save events under Realm settings, Events. IMPERSONATE and IMPERSONATE_ERROR are among the types saved by default (opens in a new tab) once storage is on. Keycloak 26.8.0 also adds impersonator and impersonator_id details to token events such as CODE_TO_TOKEN and REFRESH_TOKEN.
Your backend needs the impersonator too. From Keycloak 26.8.0, access and ID tokens issued from an impersonation session always carry an act (actor) claim (opens in a new tab) that identifies the impersonator. You can also add the predefined Impersonator User ID and Impersonator Username session-note mappers (opens in a new tab) to your client. Tokens from an impersonated session then carry impersonator.id and impersonator.username claims (opens in a new tab) (abridged, placeholder IDs):
{ "sub": "customer-user-id", "impersonator": { "id": "staff-user-id", "username": "support-ana" } }
Two gaps remain. The impersonation endpoint takes no reason, so nothing records why. And an impersonated session is an ordinary user session, so the realm’s SSO Session Idle and SSO Session Max timeouts apply rather than a support-specific limit. You can end it from the user’s Sessions tab, but signing a session out doesn’t revoke access tokens already issued: Keycloak’s guide to administering sessions (opens in a new tab) notes that after Sign out all active sessions, outstanding access tokens must expire naturally. Keep access token lifespans short for clients support uses.
What does a support workflow add?
| Requirement | What Keycloak provides | What your team decides |
|---|---|---|
| Open the customer’s account | Impersonate action and Admin REST endpoint | Who uses it, and from where |
| Limit who can impersonate whom | FGAP v2 per user or group | Ticket or assignment checks |
| Tell staff and customer apart | Session notes and impersonator mappers (opens in a new tab) | Recording both in your business audit events |
| Record what happened | IMPERSONATE event | Reason, approver and scope |
| Limit time | Realm session timeouts | A window per investigation |
| Restrict actions | Nothing for impersonated sessions | Which routes are blocked during support access |
The impersonation audit log guide covers what to record alongside Keycloak’s event.
How does Devora fit with Keycloak?
Plainly: Devora has no Keycloak recipe. Its documented provider routes (opens in a new tab) are Clerk, Better Auth, Auth0, WorkOS and a custom session bridge. Devora hasn’t built or tested a route that turns an approval into a Keycloak session, through the Admin API or token exchange.
If your application creates its own session after Keycloak sign-in, the custom one-time session bridge (opens in a new tab) can work:
- After a Devora approval, your
IMPERSONATEhandler confirms the target user and returns a short-lived, one-time handoff token. - Your app exchanges it once for its own HTTP-only support session that stores Devora’s context unchanged and expires no later than the approval.
- Your backend passes that context to Devora’s guard (opens in a new tab), which enforces read or write scope and the time limit.
- Your
TERMINATEhandler revokes support sessions indexed by Devora’s session ID.
Devora handles the request, the approval by an approver or admin in your organization, scope, time limit and access history, as its overview for teams (opens in a new tab) describes. Your app still owns authentication, tenant authorization and business audit events. If your APIs only accept Keycloak-issued tokens, this bridge doesn’t fit, and Keycloak’s own Impersonate action stays separate from Devora’s workflow.
Test it in staging
Use synthetic users and record your Keycloak version. These are pass conditions to check, not results we’ve run.
| Scenario | Pass condition |
|---|---|
Help desk admin with FGAP impersonate-members on one group | Can impersonate members of that group only |
| Role audit of the same help desk admin | No impersonation or realm-admin role, so only FGAP grants apply |
| Protected admin user | Impersonation is denied |
| Impersonated request to your API | Backend sees impersonator.id and the customer’s sub as different identities |
| Event storage on | IMPERSONATE event shows the impersonator |
| Session signed out mid-investigation | Your API rejects the next request once the access token expires |
If Keycloak’s native tools cover your needs, keep them. If you need per-request approvals, scoped access and access history, and your app owns its session, create a Devora account and try one staging session through the custom bridge.
Sources
- Keycloak Server Administration Guide: Administering sessions (opens in a new tab)
- Keycloak source (26.8.0): UserResource impersonation endpoint (opens in a new tab)
- Keycloak: Enabling and disabling features (opens in a new tab)
- Keycloak 26.8.0 release notes (opens in a new tab)
- Keycloak GitHub discussion #29902: Fine Grained Impersonations (opens in a new tab)
- Keycloak: Configuring and using token exchange (opens in a new tab)
- Keycloak source (26.8.0): EventType (opens in a new tab)
- Keycloak source (26.8.0): ImpersonationSessionNote (opens in a new tab)
- Devora: Authentication providers (opens in a new tab)
- Devora: Custom JWT or cookie session (opens in a new tab)
- Devora: Scope and security (opens in a new tab)
- Devora: Overview for teams (opens in a new tab)