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.
keycloak
container automatically imports a default realm with users. You can learn how to import a realm in the Keycloak in Docker #2 – How to import a Keycloak realm post.keycloak:keycloak
.user
realm role by default.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:
What’s more, we can combine these approaches to fine-tune permission management.
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
https://www.keycloak.org/docs/16.0/server_admin/#global-rolesadmin
role are super users and have full access to manage any realm on the server. Users with thecreate-realm
role are allowed to create new realms. They will be granted full access to any new realm they create.
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.
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.
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.
We can manage a common set of user privileges and role mappings by assigning them to Keycloak groups.
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.
https://www.keycloak.org/docs/16.0/server_admin/#proc-managing-groups_server_administration_guide
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.
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.
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:
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.
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
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.
Photo by Mikhail Nilov from Pexels
Spring Security allows us to use role-based control to restrict access to API resources. However,…
A custom annotation in Spring Boot tests is an easy and flexible way to provide…
Delegating user management to Keycloak allows us to better focus on meeting the business needs…
Swagger offers various methods to authorize requests to our Keycloak secured API. I'll show you…
Configuring our Spring Boot API to use Keycloak as an authentication and authorization server can…
Keycloak provides simple integration with Spring applications. As a result, we can easily configure our…
View Comments
Nice Article
Very nice post