It can't set view_users
role at the client creation time.
It can be assign after creation by separate API (client role mapping)
curl --location --request POST 'http://localhost:8180/auth/admin/realms/$REALM_NAME/users/$SERVICE_ACCOUNT_USER_ID/role-mappings/clients/$REALM_MANAGEMENT_CLIENT_ID' \
--header 'Authorization: Bearer $MASTER_TOKEN' \
--header 'Content-Type: application/json' \
--data-raw '[
{
"id":$VIEW_USER_ID,
"name":"view-users",
"description":"${role_view-users}",
"composite":true,
"clientRole":true,
"containerId":$REALM_MANAGEMENT_CLIENT_ID
}
]'
Three items is required to this API.
$SERVICE_ACCOUNT_USER_ID
$REALM_MANAGEMENT_CLIENT_ID
$VIEW_USER_ID
This is demo steps
I am using Keycloak v18.0.2
, curl
,jq
and git bash terminal
at Windows 10
(It will be no problem in linux too)
All captured image will be following after curl
command as a result.
Step 3 & 7 are key steps

I will demo all of API call by curl
#1 Set {credential, client name, realm name}
MASTER_USERNAME=admin
MASTER_PASSWORD=admin
REALM_NAME=my-realm
CLIENT_NAME=demo
echo '$MASTER_USERNAME = '$MASTER_USERNAME
echo 'MASTER_PASSWORD = '$MASTER_PASSWORD
echo 'REALM_NAME = '$REALM_NAME
echo 'CLIENT_NAME= '$CLIENT_NAME

#2 Get master token
more detail in here
MASTER_TOKEN_URL=$(curl --location --request GET 'http://localhost:8180/auth/realms/master/.well-known/openid-configuration' | jq -r '.token_endpoint')
echo $MASTER_TOKEN_URL

MASTER_TOKEN=$(curl --location --request POST "$MASTER_TOKEN_URL" \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=admin-cli' \
--data-urlencode 'username='$MASTER_USERNAME \
--data-urlencode 'password='$MASTER_PASSWORD \
--data-urlencode 'grant_type=password' | jq -r '.access_token')
echo 'MASTER_TOKEN = '$MASTER_TOKEN

#3 Create client
curl --location --request POST 'http://localhost:8180/auth/admin/realms/'$REALM_NAME'/clients' \
--header 'Authorization: Bearer '$MASTER_TOKEN \
--header 'Content-Type: application/json' \
--data-raw '{
"clientId":"'$CLIENT_NAME'",
"enabled":true,
"consentRequired": false,
"attributes":{},
"serviceAccountsEnabled": true,
"protocol":"openid-connect",
"publicClient":false,
"authorizationServicesEnabled": true,
"clientAuthenticatorType":"client-secret",
"redirectUris":["http://localhost:8180/demo"]
}'

#4 Get {service-account-user-id}
SERVICE_ACCOUNT_USER_ID=$(curl --location --request GET 'http://localhost:8180/auth/admin/realms/'$REALM_NAME'/users/?username=service-account-'$CLIENT_NAME \
--header 'Authorization: Bearer '$MASTER_TOKEN | jq -r .[0].id)
echo 'SERVICE_ACCOUNT_USER_ID = '$SERVICE_ACCOUNT_USER_ID

#5 Get {realm-management-client-id}
REALM_MANAGEMENT_CLIENT_ID=$(curl --location --request GET 'http://localhost:8180/auth/admin/realms/'$REALM_NAME'/clients' \
--header 'Authorization: Bearer '$MASTER_TOKEN | jq -r '. | map(select(.clientId == "realm-management")) | .[0].id')
echo 'REALM_MANAGEMENT_CLIENT_ID = '$REALM_MANAGEMENT_CLIENT_ID

#6 Get {view_user_role_id}
VIEW_USERS_ID=$(curl --location --request GET 'http://localhost:8180/auth/admin/realms/'$REALM_NAME'/clients/'$REALM_MANAGEMENT_CLIENT_ID'/roles' \
--header 'Authorization: Bearer '$MASTER_TOKEN | jq -r '. | map(select(.name == "view-users")) | .[0].id')
echo 'VIEW_USERS_ID = '$VIEW_USERS_ID

#7 Assign view-users
role to client
curl --location --request POST 'http://localhost:8180/auth/admin/realms/'$REALM_NAME'/users/'$SERVICE_ACCOUNT_USER_ID'/role-mappings/clients/'$REALM_MANAGEMENT_CLIENT_ID \
--header 'Authorization: Bearer '$MASTER_TOKEN \
--header 'Content-Type: application/json' \
--data-raw '[
{
"id":"'$VIEW_USERS_ID'",
"name":"view-users",
"description":"${role_view-users}",
"composite":true,
"clientRole":true,
"containerId":"'$REALM_MANAGEMENT_CLIENT_ID'"
}
]'

#8 confirm it
Finally, you can confirm it by curl or UI
curl --location --request GET 'http://localhost:8180/auth/admin/realms/my-realm/users/'$SERVICE_ACCOUNT_USER_ID'/role-mappings/clients/'$REALM_MANAGEMENT_CLIENT_ID \
--header 'Authorization: Bearer '$MASTER_TOKEN | jq --indent 4

