Keycloak and Enterprise Identity
Role and Group Mapping, and Confirming It in the Token
Goal
Create realm roles, client roles, groups, and composite roles, see for yourself how they are carried in the token, and even learn how to narrow the token with scope.
Why it matters
"I gave the role but it doesn't show in the token" is a problem every team using Keycloak experiences at least once. The cause is usually one of three. Either you do not know that realm roles and client roles go into different paths of the token (realm_access.roles versus resource_access.<클라이언트>.roles, where the latter takes the client), or the client's full scope allowed is turned off, or you expected group inheritance but the mapping is not in place. This lab has you create each of the three and see them with your own eyes. In particular, the scope restriction in step 7 is a practical technique for reducing token size and keeping least privilege, and at the same time it is a frequent cause of this very problem.
Steps
- In realm
labhub2, create realm rolesorder-readerandorder-admin.kcadm.sh get roles -r labhub2must show both. - In client
api-svc, create the client rolerefund. - Grant user
dev1the realm roleorder-readerand the client rolerefund. - Get a password-grant token as
dev1and save the payload to/root/kr/claims.json.realm_access.rolesmust haveorder-readerandresource_access.api-svc.rolesmust haverefund. - Create the group
team-payments, map the realm roleorder-adminto it, and putdev1in that group. In the new token'srealm_access.roles,order-adminmust appear. In/root/kr/group.txt, writegroup=team-payments inherited=order-admin. - Make
order-admina composite role that includesorder-reader. In/root/kr/composite.txt, writecomposite=true includes=order-reader. - For client
web-app, changefullScopeAllowedto false and check whetherorder-admindrops out of a token obtained with that client. In/root/kr/scope.txt, writefull_scope=false order_admin_in_token=false.
Notes
- Granting a role:
kcadm.sh add-roles -r labhub2 --uusername dev1 --rolename order-reader - Granting a client role:
kcadm.sh add-roles -r labhub2 --uusername dev1 --cclientid api-svc --rolename refund - For the token payload, just Base64URL-decode the second piece.
- Common mistake 1: looking for a realm role in
resource_access. - Common mistake 2: putting only the user in the group and omitting the role mapping — the group itself does not grant permissions.
Create realm roles
In realm labhub2, create realm roles order-reader and order-admin. kcadm.sh get roles -r labhub2 must show both.
These are roles meaningful across the whole realm. If you create two, you can bundle them as a composite later.
Create a client role
In client api-svc, create the client role refund.
It is meaningful only within a specific client. It prevents name collisions when there are several services.
Grant roles to a user
Grant user dev1 the realm role order-reader and the client role refund.
The way the grant command specifies its target differs between realm roles and client roles.
Check that the roles are carried in the token
Get a password-grant token as dev1 and save the payload to /root/kr/claims.json. realm_access.roles must have order-reader and resource_access.api-svc.roles must have refund.
The JSON paths where realm roles and client roles go are different from each other.
Create a group, map a role, and add a user
Create the group team-payments, map the realm role order-admin to it, and put dev1 in that group. In the new token's realm_access.roles, order-admin must appear. In /root/kr/group.txt, write group=team-payments inherited=order-admin.
Instead of giving it individually to 300 users, give it to the group and put the users in. It is inherited.
Build a composite role
Make order-admin a composite role that includes order-reader. In /root/kr/composite.txt, write composite=true includes=order-reader.
A role contains other roles. Even if you give only the parent role, the child role should be carried along with it.
Try excluding a role from the token with scope
For client web-app, change fullScopeAllowed to false and check whether order-admin drops out of a token obtained with that client. In /root/kr/scope.txt, write full_scope=false order_admin_in_token=false.
If you turn off the client's full scope allowed, roles that are not mapped drop out of the token.