I want to create a user and assign a client role with it in a single
API in Keycloak I have attached the details.
Unfortunately, it is impossible to do that with a single API call, even though the Keycloak Admin rest API documentation infers otherwise. This can be confirmed by looking at this GitHub issue. Quoting the reply from that thread (from the Keycloak Project Leader Stian Thorgersen):
So, unfortunately, the answer from @Devendra Mahajan is simply not correct.
The solution is to perform two calls, namely:
- one to create the user
- another to assign the roles
First create the user using the endpoint POST /{realm}/users
and with the following data (without the role):
{
"username": "joshbiden",
"enabled": true,
"firstName": "Josh",
"lastName": "biden",
"email": "email@gmail.com",
"attributes": {
"Mobile Number": [
"3333332332"
]
},
"credentials": [{
"type":"password",
"value":"rollback",
"temporary":false
}]
}
Second, you assign the role using the endpoint :
POST /{realm}/users/{id}/role-mappings/clients/{id of client}
with the data:
[{
"id": "32e432da-d0c0-45f8-a67d-f3146b7a24b4",
"name": "DEVELOPER",
"composite": false,
"clientRole": true,
"containerId": "343434-7631-4187-ac76-ad78de119b90"
}]
Step-by-Step
Warning: 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 use Keycloak Admin REST API you need an access token from a user with the proper permissions. 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 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 create the user in your realm $REALM_NAME
:
curl -X POST "https://${KEYCLOAK_HOST}/auth/admin/realms/${REALM_NAME}/users"
-H "Content-Type: application/json" \
-H "Authorization: bearer $ACCESS_TOKEN" \
-d "${USER_JSON_DATA}"
For those that need you can also have a look at my scripts to automatize the user creation on GitHub, namely this or this.
To assign the client role to the user you need the know beforehand the following fields:
- id of the user
- id of the client
- client role representation
To get the user id from your realm $REALM_NAME
:
curl -X GET "https://${KEYCLOAK_HOST}/auth/admin/realms/${REALM_NAME}/users/?username=${USERNAME}" \
-H "Content-Type: application/json" \
-H "Authorization: bearer $ACCESS_TOKEN"
From the response extract the user id
for example as follows
jq -r ".[] | select(.username==\"$USERNAME\")" | jq -r id
and save it in the variable ${USER_ID}
.
To get the client id
call the endpoint get clients with the parameter clientID
:
curl -X GET "${KEYCLOAK_HOST}/auth/admin/realms/${REALM_NAME}/clients?clientId=${CLIENT_ID}" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${ACCESS_TOKEN}"
Extract id from the response (e.g., jq -r .[0].id) and save it in variable ${ID_OF_CLIENT}
.
With the previous id
you can get the client role as follows:
curl -X GET "http://${KEYCLOAK_HOST}/auth/admin/realms/${REALM_NAME}/clients/${ID_OF_CLIENT}/roles/${ROLE_NAME}" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${ACCESS_TOKEN}"
Save the json response in ${CLIENT_ROLE}
, and assign the role to the user as follows:
curl -X POST "http://${KEYCLOAK_HOST}/auth/admin/realms/${REALM_NAME}/users/${USER_ID}/role-mappings/clients/${ID_OF_CLIENT}" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-d "${CLIENT_ROLE}"
I have created scripts for the aforementioned steps that can be accessed here and executed using the script getClientRoleByName.sh.