Tools

Keycloak in Docker #4 – How to define user privileges and roles

Keycloak offers a wide variety of methods for defining user permissions and roles. We can configure privileges across a realm or a specific client application. In addition, we can combine permissions by assigning users to groups or creating composite roles.

Prerequsities

User roles in Keycloak

Role is an abstraction that helps to incorporate access details and privileges into a convenient concept. Thanks to this, we can easily assign a set of permissions to users, user groups or more complex roles.

Keycloak roles are defined in a dedicated namespace so that all users with the same roles have identical permissions in that namespace. In other words, realm-level roles are a global namespace for a given realm, while client roles are namespaces intended for specific applications.

In summary, we can manage user permissions in Keycloak with:

  • Realm roles,
  • Client roles,
  • Groups,
  • Composite roles.

What’s more, we can combine these approaches to fine-tune permission management.

Master realm roles

Master is a unique realm that is available by default to allow admins to control other realms. Here we can create multiple super users who will be able to manage all or only selected realms. The documentation specifies two default realm-level roles for master: admin and create-realm:

Users with the admin role are super users and have full access to manage any realm on the server. Users with the create-realm role are allowed to create new realms. They will be granted full access to any new realm they create.

https://www.keycloak.org/docs/16.0/server_admin/#global-roles

Master views other realms as clients with the -realm suffix appended to their names. Consequently, in our example Keycloak server, the Example-Realm-realm is listed among the clients of the master realm:

Furthermore, we can check the role mappings for our default admin account:

Additionally, we can find more details and specifications of the experimental features in the Master realm access control section of the Keycloak documentation.

Realm roles

We need to select Example-Realm to view all roles available in it. In addition to the default offline_access and uma_authorization roles, we can see a role that I created specifically for this realm – user:

In order to see users associated with a given role, click the role name and go to the Users in Role tab:

The roles defined within a realm will be effective across all its clients. As a result, we can use them to provide more coarse-grained access control.

Client roles

In Keycloak, each client gets its own role namespace to hold user roles. Roles defined in one client are invisible to other clients. First, we’re going to create a sample application for our realm:

Then, we can select the Roles tab and click the Add Role button to create the employee role. Finally, we can see all roles assigned to that particular client, just like on the screenshot below:

Now we can assign this role to users. Keep in mind that this role is only effective for that particular client. It won’t be added to the realm namespace by default, nor will it be visible for other clients.

To see users with a specific role, click the role name and select the Users in Role tab. In addition, we can also preview what client roles will be included in the access token for a given user. Go to Clients → Client Scopes → Evaluate, select a user, click the Evaluate button and go to the Generated Access Token tab, as shown on the screenshot below:

The client roles are listed in the resource_access section of the token.

Groups

We can manage a common set of user privileges and role mappings by assigning them to Keycloak groups.

Group hierarchy and role inheritance

In order to simplify user management, we can utilize privilege inheritance. According to the hierarchy described in the documentation:

A group can have multiple subgroups but a group can have only one parent. Subgroups inherit the attributes and role mappings from their parent. Users inherit the attributes and role mappings from their parent as well.


If you have a parent group and a child group, and a user that belongs only to the child group, the user in the child group inherits the attributes and role mappings of both the parent group and the child group.

https://www.keycloak.org/docs/16.0/server_admin/#proc-managing-groups_server_administration_guide

Let’s explore this concept on a practical example. As an illustration, I want to assign privileges to users according to the following scheme:

First, I’m going to create all the roles (publish-release, manage-issue, etc.). For this example, I am creating realm-level roles.

Second, I’m going to create groups and subgroups in the Keycloak groups management view. As a result, I have the structure shown in the screenshot below:

Then we can assign our roles to the created groups. To do this, edit a group, go to the Role Mappings tab, select the roles from the Available Roles list and click Add selected. In the screenshot below, you can see the role mapping for the dev-ops group:

Finally, I’m going to assign one of the realm users, carlo, to the dev-ops group:

When we examine his role mappings, we see that his effective roles include not only those directly related to the dev-ops group (manage-issue, publish-release, schedule-downtime), but also those assigned to the development group (create-feature-branch, create-merge-request):

Moreover, the only role I have manually assigned to him is user. Therefore, this is the only role I can manually remove from his role mappings. To remove roles that he has acquired through membership in a specific group, we need to remove him from that group.

Combining realm and client level roles

Earlier in this article, I created a client-level role – the employee role. I can assign this role to all members of the development group:

As a result, members will have realm-level roles recognized by all clients (e.g. create-feature-branch) and a client-level role (employee) visible only to the example-client application. We can see the result in the effective roles mappings for carlo:

Composite roles

Both realm and client-level roles can be marked as Composite. Thanks to this, we can assign them additional roles. In other words, a service with a composite role obtains all the roles associated with that composite. It’s important to realise that we shouldn’t overuse composites as recursive inheritance can lead to convoluted mappings.

Let’s create a client-level role – admin-service, mark it as a composite role and associate it with the backup-database and crawl-pages roles:

Consequently, by assigning the admin-service role to an application, we also grant it all associated roles. As we can see, we can easily assign a complex set of permissions to services and applications.

Groups vs composite roles

The functions provided by the groups and the composite roles overlap and we technically can achieve the same goal with each of them. However, we should manage users with the former and applications with the latter. As we can read in the docs:

Composite Roles are similar to Groups as they provide the same functionality. The difference between them is conceptual. Composite roles apply the permission model to a set of services and applications. Use composite roles to manage applications and services.

Groups focus on collections of users and their roles in an organization. Use groups to manage users.

https://www.keycloak.org/docs/16.0/server_admin/#con-comparing-groups-roles_server_administration_guide

In addition, in the keycloak-dev mailing list archives from 2015 we can read:

So, keycloak composite roles would be a way to organise rights for a set of applications. (…) Conversely, a keycloak group would provide a way to organize a set of users. (…) Really, in Keycloak with composite roles, you can have a role act as a group. So, while groups and roles are logically the same adding the concept of a group though provides distinction and clarity without overloading the concept of a composite.

https://lists.jboss.org/pipermail/keycloak-dev/2015-November/005735.html

Exporting Keycloak realm with user roles

Keycloak Admin console supports exporting realms. The following example shows how to save a realm with the groups, roles and its clients that we’ve created so far.

First, select the Export option from the menu and check the Export groups and roles and Export clients checkboxes:

You’ll get the realm-export.json file that you can save on your machine. Inside you’ll find the roles for Example-Realm and example-client:

{
  "id": "Example-Realm",
  …
  "roles": {
    "realm": [
      {
        "id": "a498ea58-eb70-4c6f-a7f7-fefb0c3feaf3",
        "name": "create-merge-request",
        "description": "Can create a merge request in the repo.",
        "composite": false,
        "clientRole": false,
        "containerId": "Example-Realm",
        "attributes": {}
      },
      {
        "id": "1d5a18c3-7780-4357-b41b-77d8b7083433",
        "name": "offline_access",
        "description": "${role_offline-access}",
        "composite": false,
        "clientRole": false,
        "containerId": "Example-Realm",
        "attributes": {}
      },
      {
        "id": "40ac85fc-3804-49fc-870e-be141b60350e",
        "name": "create-feature-branch",
        "description": "Can create a feature branch in the repo.",
        "composite": false,
        "clientRole": false,
        "containerId": "Example-Realm",
        "attributes": {}
      },
      {
        "id": "0e9b7666-2ad3-4393-a962-fa7c0652bc2b",
        "name": "schedule-downtime",
        "description": "Can manage the downtime schedule for the app.",
        "composite": false,
        "clientRole": false,
        "containerId": "Example-Realm",
        "attributes": {}
      },
      …
    ],
    "client": {
      "example-client": [
        {
          "id": "c08e7cb3-5330-4441-9112-20dc28d21ce6",
          "name": "employee",
          "description": "Can view their own work schedule.",
          "composite": false,
          "clientRole": true,
          "containerId": "97bfdbcb-6376-4b04-8a69-34fd8c6cd73b",
          "attributes": {}
        },
        {
          "id": "2530963f-f7a8-454f-895d-51b804a55248",
          "name": "backup-database",
          "description": "Run a scheduled automated database backup.",
          "composite": false,
          "clientRole": true,
          "containerId": "97bfdbcb-6376-4b04-8a69-34fd8c6cd73b",
          "attributes": {}
        },
        {
          "id": "a37df70c-8dd9-4aa3-816f-759f830e669a",
          "name": "admin-service",
          "description": "Perform automated administration tasks.",
          "composite": true,
          "composites": {
            "client": {
              "example-client": [
                "backup-database",
                "crawl-pages"
              ]
            }
          },
          "clientRole": true,
          "containerId": "97bfdbcb-6376-4b04-8a69-34fd8c6cd73b",
          "attributes": {}
        },
        {
          "id": "5aa70d72-d5ce-4feb-9f22-6c1e63ac987c",
          "name": "crawl-pages",
          "description": "Run an automated web crawler.",
          "composite": false,
          "clientRole": true,
          "containerId": "97bfdbcb-6376-4b04-8a69-34fd8c6cd73b",
          "attributes": {}
        }
      ],
    …

If you don’t want to lose these roles when you delete the keycloak containers and their associated volumes, replace the realm-export.json file assigned to the following volume in the docker-compose-keycloak.yml file:

# docker-compose-keycloak.yml
services:
  keycloak:
    …
    volumes:
      - ./keycloak/realms/realm-export.json:/tmp/realm-export.json

However, we won’t be able to include users in the file created from the Admin console export. Therefore, if you need to export users as well, follow directions provided in the Keycloak in Docker #5 – How to export a realm with users and secrets post or Importing and exporting the database section of the documentation.

If you want to keep the default users and still export realm from the Admin console, just copy the users array from the default-users.json file to your new realm-export.json file.

Read more on user roles in Keycloak

Photo by Mikhail Nilov from Pexels

little_pinecone

View Comments

Recent Posts

Simplify the management of user roles in Spring Boot

Spring Security allows us to use role-based control to restrict access to API resources. However,…

3 years ago

Create a custom annotation to configure Spring Boot tests

A custom annotation in Spring Boot tests is an easy and flexible way to provide…

3 years ago

Keycloak with Spring Boot #4 – Simple guide for roles and authorities

Delegating user management to Keycloak allows us to better focus on meeting the business needs…

3 years ago

Keycloak with Spring Boot #3 – How to authorize requests in Swagger UI

Swagger offers various methods to authorize requests to our Keycloak secured API. I'll show you…

3 years ago

Keycloak with Spring Boot #2 – Spring Security instead of Keycloak in tests

Configuring our Spring Boot API to use Keycloak as an authentication and authorization server can…

3 years ago

Keycloak with Spring Boot #1 – Configure Spring Security with Keycloak

Keycloak provides simple integration with Spring applications. As a result, we can easily configure our…

3 years ago