4

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

Ernest Poldrige
  • 399
  • 1
  • 6
  • 17

2 Answers2

1

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

Thanks

Subodh Joshi
  • 12,717
  • 29
  • 108
  • 202
Ernest Poldrige
  • 399
  • 1
  • 6
  • 17
1

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>'
Dharman
  • 30,962
  • 25
  • 85
  • 135