Keycloak’s Admin REST API doesn’t just let you manage users; it’s the only way to get granular control over user lifecycles in a truly automated fashion.

Let’s see it in action. Imagine we need to create a new user, assign them to a specific role, and then immediately disable their account. We can do this with a few curl commands.

First, we need an access token to authenticate with the Admin API. This usually involves a service account or a dedicated admin user. For this example, let’s assume we have a service account client configured with the realm-admin role.

curl -X POST \
  http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=password' \
  -d 'username=adminuser' \
  -d 'password=adminpassword' \
  -d 'client_id=my-admin-client' \
  -d 'scope=openid'

This will return a JSON object containing access_token. We’ll use this token for subsequent requests.

Now, let’s create a user. We’ll specify the username, email, and that the user must set a password on their first login.

ACCESS_TOKEN="eyJ..." # Replace with your actual access token

curl -X POST \
  http://localhost:8080/auth/admin/realms/myrealm/users \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "username": "newuser123",
    "enabled": true,
    "email": "newuser@example.com",
    "requiredActions": ["VERIFY_EMAIL", "UPDATE_PASSWORD"]
  }'

Next, we need the ID of the user we just created. You can get this by querying for the user and filtering by username.

USER_ID=$(curl -X GET \
  http://localhost:8080/auth/admin/realms/myrealm/users?username=newuser123 \
  -H "Authorization: Bearer $ACCESS_TOKEN" | jq -r '.[0].id')

echo "Created User ID: $USER_ID"

Now, let’s assign a role to this user. First, we need to find the ID of the role we want to assign. Let’s say we want to assign the user role.

ROLE_ID=$(curl -X GET \
  http://localhost:8080/auth/admin/realms/myrealm/roles | jq -r '.[] | select(.name=="user") | .id')

echo "Role ID: $ROLE_ID"

With both user and role IDs, we can now assign the role.

curl -X POST \
  http://localhost:8080/auth/admin/realms/myrealm/users/$USER_ID/role-mappings/realm \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d "[{\"id\": \"$ROLE_ID\", \"name\": \"user\"}]"

Finally, let’s disable the user.

curl -X PUT \
  http://localhost:8080/auth/admin/realms/myrealm/users/$USER_ID \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "enabled": false
  }'

This sequence demonstrates how you can programmatically orchestrate user lifecycle events. The Admin REST API exposes endpoints for virtually every administrative task, from creating and deleting users to managing their groups, roles, credentials, and even their session information.

The core problem the Admin API solves is bridging the gap between a human-driven administrative interface and the need for automated, scalable user management. This is crucial for onboarding new users in bulk, integrating with HR systems, implementing self-service account management features, or enforcing complex security policies dynamically. You’re essentially giving your applications the power to act as administrators, but with the precision and speed of code.

The requiredActions field is more powerful than it appears. When you set UPDATE_PASSWORD, Keycloak doesn’t just flag it; it actively prevents the user from logging in with a password until that action is completed through the user-facing flows. This is enforced at the token issuance level, meaning any attempt to authenticate will be rejected until the user performs the required action.

The next logical step is to explore how to manage user groups and their associated permissions programmatically.

Want structured learning?

Take the full Keycloak course →