Ernest Poldrige
Ernest Poldrige

Reputation: 429

Keycloak access impersonate API

We started using keycloak 3.4.3 and we need to introduce an impersonate function in our application. We found that keycloak has an impersonate api which unfortunate it does not return a token for the user but a redirect link for which the user can "select" his own client.

We found here

https://blog.softwaremill.com/who-am-i-keycloak-impersonation-api-bfe7acaf051a

a way (in scala) to retrieve a fresh token (only for keycloak 3.4+):

    private def exchangeToken(token: String, userId: String): Future[TokenResponse] = {
  import io.circe.generic.auto._
  sttp
    .post(uri"${config.authServerUrl}/realms/${config.realm}/protocol/openid-connect/token")
    .body(
      "grant_type" -> "urn:ietf:params:oauth:grant-type:token-exchange",
      "client_id" -> config.clientId,
      "requested_subject" -> userId,
      "subject_token" -> token
    )
    .response(asJson[TokenResponse])
    .send()
    .flatMap {
      _.body match {
        case Left(error) => Future.failed(new RuntimeException(error))
        case Right(Left(circeError)) => Future.failed(circeError)
        case Right(Right(tokenResponse)) => Future.successful(tokenResponse)
      }
    }
}

I tried to create a curl command based on it:

curl --verbose -X POST "http://<host>/auth/realms/master/protocol/openid-connect/token" \
 -H "Content-Type: application/x-www-form-urlencoded" \
 --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
 -d 'client_id=admin_cli' \
 -d "requested_subject=${USER_ID}" \
 -d "subject_token=${TKN}" 

but I got error "invalid_client_credentials". Client "admin_cli" has access_type as "public". I tried adding the authorization token as a bearer but still got the same error.

Have I missed something to configure ? Or is the curl command missing some parameter ?

Thanks for any help

Upvotes: 6

Views: 9550

Answers (2)

chaitanya guruprasad
chaitanya guruprasad

Reputation: 691

I hope it is not too late to answer. We can get the access token of the impersonated(tony123) by using the credentials of the impersonator(superadmin). Below are the steps I followed.

  1. Created superadmin user. I gave him the role impersonation which is found under Users -> superadmin -> Role Mappings -> client roles -> Realm-management
  2. Get access token for superadmin using
curl --location --request POST 'http://localhost:8180/auth/realms/tenant/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username=superadmin' \
--data-urlencode 'password=<superadmin-password>' \
--data-urlencode 'client_id=<source-client-id>' \
--data-urlencode 'client_secret=<source-client-secret>'
  1. Now get the impersonated user's token using the below curl
curl --location --request POST 'http://localhost:8180/auth/realms/tenant/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=<source-client-id>' \
--data-urlencode 'client_secret=<source-client-secret>' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
--data-urlencode 'subject_token=<access token got in step one>' \
--data-urlencode 'requested_token_type=urn:ietf:params:oauth:token-type:access_token' \
--data-urlencode 'requested_subject=<user id of tony123>'

Upvotes: 3

Ernest Poldrige
Ernest Poldrige

Reputation: 429

I solved the issue, it was a simple typo in the curl command admin_cli instead of admin-cli.

Thanks

Upvotes: 1

Related Questions