Skip to content

Roles

A role is a named permission tag that you attach to users (or groups). When a user authenticates, Keycloak embeds their roles in the token. Your application reads those roles from the token and decides what the user is allowed to do — no extra database call needed.

Keycloak has two flavours of roles:

  • Realm roles — defined at the realm level. Available to any client in the realm.
  • Client roles — defined on a specific client. Scoped to that client.

Realm roles apply across the entire realm. They are a good fit for coarse-grained, application-wide permissions like admin, support-agent, or billing-viewer that may be relevant to more than one application.

  1. In the admin console, make sure you are in the correct realm.
  2. Click Realm roles in the left sidebar.
  3. Click Create role (top-right of the list).
  4. Enter a Role name (e.g., app-admin).
  5. Optionally add a Description.
  6. Click Save.

The role is now available to assign to users, groups, or composite roles.

Client roles are defined on a specific client and are only meaningful to that client. They are a good fit for fine-grained, application-specific permissions like orders:read, orders:write, or reports:export.

  1. In the admin console, click Clients in the left sidebar and open the client you want to add roles to.
  2. Click the Roles tab on the client.
  3. Click Create role.
  4. Enter a Role name (e.g., orders:read).
  5. Optionally add a Description.
  6. Click Save.

A composite role is a role that automatically grants all the roles it contains. Instead of assigning five individual roles to every new employee, you create one composite role (employee) that bundles them all, and assign only that.

  1. Create the child roles first (realm or client roles).
  2. Create a new realm role (e.g., employee).
  3. On the role’s detail page, click Action → Add associated roles (or look for the Associated roles tab).
  4. Search for and select the child roles you want to bundle.
  5. Click Assign.

Now assigning employee to a user automatically grants all the bundled roles.

  1. In the admin console, click Users in the left sidebar.
  2. Find the user and click their username to open their profile.
  3. Click the Role mapping tab.
  4. Click Assign role.
  5. In the filter, choose Filter by realm roles to see realm roles, or Filter by clients and select your client to see client roles.
  6. Check the box next to each role you want to assign.
  7. Click Assign.

The roles take effect immediately for new login sessions. Existing sessions are not retroactively updated until the user re-authenticates or their token is refreshed.

After a user authenticates, their access token (a JWT) contains their roles in two standard claims:

  • realm_access.roles — an array of all realm-level roles assigned to the user.
  • resource_access.{client-id}.roles — an array of client roles for that specific client.

Here is a decoded JWT payload showing both:

{
  "sub": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "preferred_username": "alice",
  "email": "[email protected]",
  "realm_access": {
    "roles": [
      "app-admin",
      "offline_access",
      "uma_authorization"
    ]
  },
  "resource_access": {
    "my-app-backend": {
      "roles": [
        "orders:read",
        "orders:write"
      ]
    },
    "account": {
      "roles": [
        "manage-account",
        "view-profile"
      ]
    }
  }
}

Your application should verify the JWT signature using the realm’s JWKS endpoint, then read roles from the claims shown above. Most OIDC libraries (Keycloak adapters, Spring Security, Passport.js, etc.) do this automatically once configured. You should never trust the token without verifying the signature.

Example: in a Node.js application using the raw JWT payload after verification:

// After jwt.verify() succeeds:
const realmRoles = token.realm_access?.roles ?? [];
const clientRoles = token.resource_access?.['my-app-backend']?.roles ?? [];
if (realmRoles.includes('app-admin')) {
// grant admin access
}

Every realm and every client ships with some built-in roles you will see in tokens:

RoleLocationPurpose
offline_accessRealmAllows requesting offline tokens (long-lived refresh tokens)
uma_authorizationRealmGrants access to the UMA authorisation API
manage-accountaccount clientLets the user manage their own account
view-profileaccount clientLets the user view their profile

You do not need to assign uma_authorization or offline_access to users manually; they are granted by default via the default-roles-{realm} composite role.

OptionBenefitCost
Realm roleUsable across every client in the realm — good for coarse-grained permissions shared across appsCannot be scoped to a single client; you need a client role if you need finer granularity
Client roleScoped to one client only — good for fine-grained, app-specific permissions (e.g. orders:write)Must be redefined in every client that needs a similar permission, harder to manage across many clients
Group + role vs. assigning roles directly to usersAssigns a role to many people at once through a single group — easy to manage as people join and leave a teamThe group structure must be designed well up front; a wrong structure is hard to fix later
  • Assigning roles to users one by one instead of using a group — when employees join or change position often, assigning roles individually is error-prone and roles get missed. Attach roles to a group and put users in the group instead.
  • Using only client roles with no realm role at all, even for a permission shared across apps — this forces you to redefine the same role repeatedly in every client, when a shared permission should be promoted to a realm role.
  • Forgetting that a new role has no effect on an existing session immediately — teams often assume a newly assigned role takes effect right away, when in fact the user must log in again or wait for a token refresh first, which can look like the configuration “isn’t working.”

Real-world example

GitHub Organizations — uses a concept similar to a realm role with team-scoped permissions: organization-level permissions (e.g. owner, member) apply across every repository, while repository-level permissions act like a client role that narrows the scope.

Enterprise onboarding through groups — many large organisations attach composite roles to a group per department (e.g. engineering, sales); when a new employee joins a team, HR only needs to add the user to the correct group and every role for that department is assigned automatically through Keycloak.

What is the difference between a realm role and a client role?
In a decoded JWT, which claim contains the user's realm-level roles?
What is a composite role?
If you assign a new role to a user, when does it take effect for an existing session?