Impersonate User Via Keycloak API?

I have a multi-tiered application based on Spring Boot and I’m incorporating admin functionality in the web tier for realm admin users that perform actions through the Keycloak API (e.g. Add User, Remove User, Initiate user password reset email, Add/Remove know application user roles, Impersonate User, etc…).

I’m having trouble abstracting “Impersonate User” through the Keycloak API. The application passes the logged in user’s Keycloak Access Token through each tier and finally calls the Keycloak API impersonate endpoint passing through the Access Token of the realm admin user performing the action and the User ID of the user we want to impersonate. The REST call is successful. The user has the “impersonate” role in Keycloak.

The realm admin user and the user to be impersonated are in the same realm.

Keycloak API Request:

POST /my_realm/users/4b6a9254-535b-40bf-8074-96a0ddd1f4e7/impersonation

Response:

{
  "redirect": "https://sso.example.com/auth/realms/my_realm/account/applications",
  "sameRealm": "true"
}

What’s the proper way to have Spring Boot’s active session for the logged in user “switch” to the user we impersonated via the API call? I figured I could just redirect the logged in user to a new location in the application and they would automatically be authenticated as the impersonated user.

If I log into my application as a user in the realm with “impersonation,” manage-users," “query-users,” and “view-users” realm management roles and visit the Keycloak User admin UI and click Impersonate for a user in the realm all I have to do is visit the sign-in URL of my front-end app and I am successfully logged in as the Impersonated user.

If I visit the sign-in URL of my front end app after invoking the impersonation endpoint of Keycloak’s Admin REST API as the logged in realm admin user, I am presented with the login page vs being logged in as the user I impersonated.

How can I get impersonation to work via the Keycloak Admin REST API?

@edgewoodsoftware I have the same problem. Did you solve it?

If you as me are looking for the answer, please don’t use POST /{realm}/users/{id}/impersonation

Instead of it use POST /{realm}/protocol/openid-connect/token and recommendations from this articles:

@siropkin so shouldn’t we use POST(/{realm}/users/{id}/impersonation) to impersonate the specific user?

could you check my comment from this link?
I would be grateful if you can provide the solution.
Thanks.

After many retries, I used the impersonate API with POST in angular front-end:

My angular local URL is: http://host.docker.internal:4201/

// The access token is inject after by the lib keycloak-angular
this._httpClient.post(
    `/realms/performa/users/${userId}/impersonation`,
    null,
    {
        headers: new HttpHeaders().append('Content-Type', 'application/x-www-form-urlencoded')
    }
).subscribe(() => {
    this.document.location = '/';
});

The trick is use the same domain for the front-end and keycloak, and use a proxy for the front-end:

// proxy.conf.json
{
  "/api": {
    "target": "http://localhost:8080/api/",
    "secure": false
  },
  "/realms": {
    "target": "http://host.docker.internal:8081/admin/",
    "secure": false
  }
}
1 Like

does anyone know which api is correct for keyclaok impersonation i am stuck since past 3 days

Hi as we upgrading to keycloak version 22, While doing impersonate via api we not able to find the class name AccountFormService, I dont see any related article to it that its deprecated or removed is there any alternate for this ?

UserSessionModel userSession = this.session.sessions().createUserSession(this.realm, this.user, this.user.getUsername(), this.clientConnection.getRemoteAddr(), “impersonate”, false, (String) null, (String) null);
AuthenticationManager.createLoginCookie(this.session, this.realm, userSession.getUser(), userSession, this.uriInfo, this.clientConnection);
jakarta.ws.rs.core.UriBuilder base = uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, “getAccountService”);
URI redirect = AccountFormService.accountServiceApplicationPage(this.uriInfo).build(new Object[]{this.realm.getName()});
result.put(“sameRealm”, sameRealm);
result.put(“redirect”, redirect.toString());
event.event(EventType.IMPERSONATE).session(userSession).user(this.user).detail(“impersonator_realm”, authenticatedRealm.getName()).detail(“impersonator”, this.authP.adminAuth().getUser().getUsername()).success();

Thanks & Regards