Keycloak roles restriction and full scopes : for security concerns, you must restrict roles to a subset through the « Full Scope Allowed » Switch as by default a client has « roles » scope as « default » so that a user will have all affected clients roles in its tokens. Learn with this article how and why you must restrict roles in tokens by turning off « full scope allowed » switch.
Role-based access control (RBAC)
Great (but uncomplete) post : https://medium.com/@nishada/keycloak-spring-boot-rbac-e8732a91909a
Roles for users
Roles are special attributes declared in clients (or direct in the realm) then affected to users. A user has a set of roles affected, just like any kind of attribute.
In the user management page, we can affect roles to a user :
In « realm roles » entry, then a special « composite role » named « default-roles-realmname » contains all roles affected by default to each new user :
Roles in tokens
From your authentication client, in the « client scopes » tab then « evaluate » subtab you can simulate an authentication for a user and get the token content.
Roles are added in the access token like this :
{
...
"realm_access": {
"roles": [
"default-roles-master",
"offline_access",
"uma_authorization"
]
},
"resource_access": {
"order-backend": {
"roles": [
"customer"
]
},
...
}
Through the « roles » scope. Disable the « roles » scope in the client and all roles will disappear.
Audience
In « aud » section in the token :
"aud": [
"order-backend",
"account"
],
It defines the clients at which the token can be used. In this example, « account » backend (a Keycloak application provided by default) and my custom « order-backend ».
« roles » scope : the firing
https://datatracker.ietf.org/doc/html/rfc6749#section-3.3
the authorization server uses the « scope » response parameter to inform the client of the scope of the access token issued.
Scope is a mechanism in OAuth 2.0 to limit an application’s access to a user’s account. An application can request one or more scopes, this information is then presented to the user in the consent screen, and the access token issued to the application will be limited to the scopes granted.
Then, during the authentication process you have the « consent screen » displayed. You give consent for a set of scopes, called by the application.
Default and optional scopes
A « default » scope is always applied, an « optional » should be called by the application during the login process.
Without any scope called, in this client (with only default parameters), we have :
- acr
- basic
- profile
- roles
Scopes mappers
Each scope is declared in « client scopes » section :
For our « roles » scope, 3 mappers :
Each mapper will add data to tokens (also in userinfo and tokenintrospect responses).
- « client roles »: get all clients roles (affected to the user) then adds them to tokens
- « realm roles »: the same for realm roles
- « audience resolve »: populates the « aud » field with all clients the user has roles affected.
« full scope allowed » : the bomb
Too many roles and audience
Let’s write an example first with 2 frontend applications and 2 backends :
« frontend » will never ask « products-management-backend », even if the user has roles from « products-management-backend » client.
Let give a try, my token is :
{
"exp": 1733135718,
"iat": 1733135658,
"jti": "54f4b469-6d02-44d1-8906-da18db54c367",
"iss": "https://zugjjqptlllqkwkawayw-keycloak.services.clever-cloud.com/realms/master",
"aud": [
"order-backend",
"master-realm",
"account",
"search-backend",
"products-management-backend"
],
"sub": "97675ccc-adbd-40df-8031-ee6f31546658",
"typ": "Bearer",
"azp": "frontend",
"sid": "2828e11a-aa0f-4e23-b782-e94a61a6c046",
"acr": "1",
"allowed-origins": [
"/*"
],
"realm_access": {
"roles": [
"default-roles-master",
"offline_access",
"uma_authorization"
]
},
"resource_access": {
"order-backend": {
"roles": [
"manager",
"support",
"customer"
]
},
"master-realm": {
"roles": [
"query-users"
]
},
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
},
"search-backend": {
"roles": [
"search"
]
},
"products-management-backend": {
"roles": [
"add"
]
}
},
"scope": "openid profile email",
"email_verified": false,
"name": "Mathieu Passenaud",
"preferred_username": "standard-user",
"given_name": "Mathieu",
"family_name": "Passenaud",
"email": "contact@please-open.it"
}
😳
« aud » contains all clients, and more with 2 defaults clients :
- account
- realm-management : yes, my user also has a realm management role (query-users) for administrative tasks.
A quick draw of the reality :
There is no limitation of what my token can do from the « frontend » client.
A checkbox
In your client scopes, the first one « clientname-dedicated » is a link to :
- specific mappers for this client
- restrict roles
And here we have the worst default parameter in Keycloak :
« Allows you to disable all restrictions. »
WHY ALL RESTRICTIONS ARE DISABLED BY DEFAULT ?
Uncheck this nightmare checkbox and assign only roles needed for this client :
Now my generated token :
{
"exp": 1733139265,
"iat": 1733139205,
"jti": "fc9ca70d-094e-4165-9c10-89ca50fa5ede",
"iss": "https://zugjjqptlllqkwkawayw-keycloak.services.clever-cloud.com/realms/master",
"aud": [
"order-backend",
"search-backend"
],
"sub": "97675ccc-adbd-40df-8031-ee6f31546658",
"typ": "Bearer",
"azp": "frontend",
"sid": "eefde5bf-f1ee-433d-9f41-13dbcf0eaf67",
"acr": "1",
"allowed-origins": [
"/*"
],
"resource_access": {
"order-backend": {
"roles": [
"manager",
"support",
"customer"
]
},
"search-backend": {
"roles": [
"search"
]
}
},
"scope": "openid profile email",
"email_verified": false,
"name": "Mathieu Passenaud",
"preferred_username": "standard-user",
"given_name": "Mathieu",
"family_name": "Passenaud",
"email": "contact@please-open.it"
}
« aud » and « resource_access » are now correctly restricted with only needed attributes, no more.
Default clients in Keycloak : correctly set
account-console
The « account-console » client corresponds to the management account console provided by Keycloak. The « account api » is behind the client « account ».
By default, « full scope allowed » is disabled with correct restrictions:
Conclusion
Never trust default parameters, you should keep a hand on every parameter in Keycloak.
Get into « client », « client scopes » then « evaluate » and see exactly what is in tokens.
- Keycloak roles restriction and full scopes - 10 décembre 2024
- How to enrich native metrics in KeyCloak - 21 août 2024
- Keycloak Authenticator explained - 7 mars 2024