As admin of a Keycloak server, how can I obtain access-token of a particular user without knowing his password? Unfortunately impersonation doesn't help me because it does not contain neither his id nor his username.
There's a feature starting from keycloak 3.4.0 called token exchange wich allows you to exchange an access token from a user with impersonation permission to get other token on behalf of the other user. You can use the token endpoint this way:
curl -X POST \
-d "client_id=starting-client" \
-d "client_secret=geheim" \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d "subject_token=...." \
--data-urlencode "requested_token_type=urn:ietf:params:oauth:token-type:access_token" \
-d "audience=target-client" \
-d "requested_subject=wburke" \
http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token
You might find this post useful too.
Related
I want to let my client application access user information from keycloak. Therefore, I created another realm (myrealm1) in keycloak and within that realm I created a new client (myclient1).
keycloak configuration:
Client configuration
Actually, I tried a lot of other combinations without success.
In the client scopes tab, I added the admin client scope
In the service account roles tab, I added the admin role
Client scope configuration
For the admin client scope, I assigned the admin role in the scope tab.
Realm role configuration
For the admin realm role, I assigned the admin role in the associated role tab.
REST API Calls
These are the REST API calls I am using
curl --location --request POST 'http://localhost:8080/realms/myrealm/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=myclient1' \
--data-urlencode 'client_secret=PehR9f95woZmEEHcKfSgPaosu1Yt6P9s' \
--data-urlencode 'grant_type=client_credentials'
Returns
{
"access_token": "eyJhbGciOiJS...",
"expires_in": 300,
"refresh_expires_in": 0,
"token_type": "Bearer",
"not-before-policy": 0,
"scope": "email profile admin"
}
So far so good, I do get a token.
curl --location --request GET 'http://localhost:8080/admin/realms/myrealm/users' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer eyJhbGciOiJS...'
Returns
HTTP 403
{
"error": "unknown_error"
}
This is not as expected. The expected result would be the user information.
Btw, I do get it working for the admin user of the master realm
curl --location --request POST 'http://localhost:8080/realms/master/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=admin-cli' \
--data-urlencode 'username=admin' \
--data-urlencode 'password=password' \
--data-urlencode 'grant_type=password'
But this is not what I want. I would like to get it working for my custom client.
Setup
I am using keycloak 19.0.3
My question
What is missing to get it working? I. e. How do I enable my client to make use of the keycloak REST APIs such as /admin/realms/myrealm/users
You need to go to:
your realm;
your Client;
then go to service account;
Click on Assign Role;
Select Filter by clients;
and search for 'realm-management'
Select and assign the desired roles.
The user sends me its id and password.
Then I want to check if it is valid on the keycloak.
I can try to log in, but the session is created in keycloak.
I even thought about to log out after logging in.
But this is very inefficient.
Is there a way to check if id and passwd are valid without creating a session?
If there was such a way, my task will be very easy.
If there is no way, I have to log in instead of my user and manage the token instead.
This is relatively more complex to implement.
As far as I know out-of-the-box there is no way to avoid creating the session.
If there is no way, I have to log in instead of my user and manage the
token instead. This is relatively more complex to implement.
Not really, since, the password and username are handed to your application, you can use the following approach:
Create in Keycloak a client (in the appropriate Realm) with direct grand access flow enabled (know as Resource Owner Password Flow in OAuth2);
Set the Access token for that client to be very short living (e.g., one minute).
Make a POST request with the username and password to the client, something as follows:
curl --request POST \
--url "http://$KEYCLOAK_HOST/auth/realms/$REALM_NAME/protocol/openid-connect/token" \
--data client_id=$CLIENT_ID \
--data username=$USERNAME \
--data password=$PASSWORD \
--data grant_type=password
If you get back as a response a token, then it means that the user credentials are valid, if not then those credentials are invalid.
In case you get back the token, you can explicitly logout the session, for instance as follows:
ACCESS_TOKEN=$(echo $TOKEN | jq -r .access_token)
SESSION_STATE=$(echo $TOKEN | jq -r .session_state)
curl -k -X DELETE "http://$KEYCLOAK_HOST/auth/admin/realms/master/sessions/$SESSION_STATE" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN"
Or since the access token is very short living, let Keycloak eventually clean up the session.
How I can set user attribute value using Keycloak Rest API?
Update: The /auth path was removed starting with Keycloak 17 Quarkus distribution. So you might need to remove the /auth from the endpoint calls presented on this answer.
To set a user attribute using the Keycloak Admin REST API; you use the endpoint:
PUT <KEYCLOAK_HOST>/auth/admin/realms/<YOUR_REALM>/users/<USER_ID>
with the payload
{"attributes":{"<ATTRIBUTE_NAME>":["<ATTRIBUTE_VALUE>"]}}
the <USER_ID> you can get it using the endpoint:
GET <YOUR_KEYCLOAK_DOMAIN>/auth/admin/realms/<YOUR_REALM>/users/?username=<THE_USERNAME>
from the JSON response, extract the field id.
Step-by-Step:
You can get that information using the Keycloak Admin REST API; to call that API, you need an access token from a user with the proper permissions. For now, I will be using the admin user from the master realm:
curl https://${KEYCLOAK_HOST}/auth/realms/master/protocol/openid-connect/token \
-d "client_id=admin-cli" \
-d "username=$ADMIN_NAME" \
-d "password=$ADMIN_PASSWORD" \
-d "grant_type=password"
You will get a JSON response with the admin's token. Extract the value of property access_token from that response. Let us save it in the variable $ACCESS_TOKEN for later reference.
To get the user id from your realm $REALM_NAME:
curl -X GET https://${KEYCLOAK_HOST}/auth/admin/realms/${REALM_NAME}/users/?username=${USERNAME}&exact=true \
-H "Content-Type: application/json" \
-H "Authorization: bearer $ACCESS_TOKEN"
From the response extract the user id for example as follows
jq -r .[].id
Or even cleaner is to passed to the
To set the user attribute:
curl -X PUT https://${KEYCLOAK_HOST}/auth/admin/realms/${REALM_NAME}/users/${USER_ID} \
-H "Content-Type: application/json" \
-H "Authorization: bearer $ACCESS_TOKEN" \
-d '{"attributes":{"<ATTRIBUTE_NAME>":["<ATTRIBUTE_VALUE>"]}}'
You can also have a look at setUser script on my GitHub repo.
i m using keycloak 8.0 and i m looking to authenticate user by calling it admin api. Below is the curl command .
curl -X POST \
http://localhost:8180/auth/realms/quickstart-serv-springboot/protocol/openid-connect/token \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Postman-Token: abf5c8bf-0d1f-4178-951d-ba6c9d385596' \
-d 'client_id=wb-auth-url-demo&username=admin-wb-auth-url-demo&password=admin&grant_type=password&client_secret=a3ffca99-e0b7-49d2-8369-b9eb15385b60'
This approach looks at sending password in clear text to keycloak server but i m looking to use challenge response system which comapres hashvalue of the password for the user. How can i do this using the admin apis ?
How can we access the Box API using the refresh token that is generated? I have followed all the steps to generate the access token and refresh token but I cannot find it anywhere how can I access the API using refresh token.
This is what I have right now:
curl -X GET -H "Authorization: Bearer <Access-Token>" "https://api.box.com/2.0/folders/0"
I am not able to do this :
curl -X GET -H "Authorization: <Refresh-Token>" "https://api.box.com/2.0/folders/0"
or
curl -X GET -H "Authorization: Bearer <Refresh-Token>" "https://api.box.com/2.0/folders/0"
Any idea how we can use the Refresh token in an API call?
The access_token is used to make Box Content API calls.
The refresh_token is used to obtain a new access_token & refresh_token pair since access_tokens expire in around 60 minutes.
curl https://api.box.com/oauth2/token
-d 'grant_type=refresh_token' \
-d 'refresh_token=<MY_REFRESH_TOKEN>' \
-d 'client_id=<MY_CLIENT_ID>' \
-d 'client_secret=<MY_CLIENT_SECRET>' \
-X POST