Returning client roles in realm for single client

Hi.

I have a short question. Assume the following scenario:

  • Newest KeyCloak instance containing realm X
  • The realm X contains two clients: A and B (authorization flow setup + password flow for testing purposes)
  • Client A has a role “ExampleRole1”,
  • Client B has a role “ExampleRole2”,
  • The realm X contains user xyz which contains both roles

I’m trying to get a token using password flow:

### Get token
POST http://localhost:8080/realms/X/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded

password=foo
&username=xyz
&client_id=A
&grant_type=password

Works fine. However in the token I’m getting roles from client_id A and also B. Why is that so? As I included client_id=A in the request I don’t expect roles from other clients to be returned. Is it possible to set it somehow in the KeyCloak?

Thanks!

Could you confirm if it is desired behavior of the KeyCloak?
For me it should work like this:
AS IS:

  • All roles (for all clients in realm) are returned
    TO BE:
  • Roles for the client specified in the request is returned

I think I’ll create a bug.

It’s not a bug, you just have to read the docs.
Having “Full Scope Allowed” set to “ON” (what is the default, unfortunately) under the “Scope” tab in client settings, yields to map all roles a user is assigned to into the token(s).
By switching it off, you can select the realm and client roles just like you want, which are then mapped into the token, if a token is issued for a user for this specific client. Own client roles are always mapped, you can’t unselect them.

1 Like

@dasniko
Thanks for the response. Your answer helped me with resolving my issue.

Instruction for other looking for an answer:

  • Open Clients tab and selected my clientId
  • In “Client Details” select “Client scopes” tab
  • In the grid there should be {clientId-dedicated} client scope available as a link
  • Click the link select “Scope” and turn off Full scope allowed

I did this in other clients and it works correctly.

Thread can be closed.

@dasniko

I’ve just realized, that once I set “Full Scope Allowed” to off, realm roles are not included into the token :-/.

However, if I leave full scope allowed to “on” and in client scopes → client roles → client ID property select my “app” as in this screenshot
obraz

it works fine.
As I’ll have many apps in my realm, this is not a solution for me :-/. What should I do?

As I wrote in my previous answer…

Full Scope On maps all roles a user is assigned to into the token.
Switching it to off let’s you select which roles should be mapped into the token, if the user is assigned to.

Everything else is depending on your use case, how you want and are able to handle/manage your requirements and settings. There is not right or wrong way to go.

Thanks for quick feedback @dasniko

Now I understand this strategy, but I’m having a problem with combining both: possibility of returning “realm roles” + “client roles” in the token (only for given client, not including other roles).

In my previous message I sent a screenshot with “Client ID” property in roles mapper under client scope. This makes the trick. However, I can have only one “user client role” mapper, so in case of having many apps this is not a solution for me and I’m looking for an advice :-/.

Hi,
Before Keycloak v25, I could add a new mapper on client dedicated scope (User Client Role) for a specific client id and it and it was displayed correctly on access_token evaluate, but in recents version of Keycloak, the same mapper it doesn’t show anymore.

I export a client config on Keycloak v24 (and older) and v25, the only difference that I saw is the client id:
V24

"protocolMappers": [
  {
    "name": "roles",
    "protocol": "openid-connect",
    "protocolMapper": "oidc-usermodel-client-role-mapper",
    "consentRequired": false,
    "config": {
      "introspection.token.claim": "true",
      "multivalued": "true",
      "userinfo.token.claim": "true",
      "id.token.claim": "true",
      "lightweight.claim": "false",
      "access.token.claim": "true",
      "claim.name": "roles",
      "jsonType.label": "String",
      "usermodel.clientRoleMapping.clientId": "integra-negocio"
    }
  }
],

V25

"protocolMappers": [
  {
    "name": "roles",
    "protocol": "openid-connect",
    "protocolMapper": "oidc-usermodel-client-role-mapper",
    "consentRequired": false,
    "config": {
      "introspection.token.claim": "true",
      "multivalued": "true",
      "userinfo.token.claim": "true",
      "id.token.claim": "true",
      "lightweight.claim": "false",
      "access.token.claim": "true",
      "claim.name": "roles",
      "jsonType.label": "String",
      "usermodel.clientRoleMapping.clientId": "af7076c3-d24b-4693-9497-1950a547c62e"
    }
  }
],

I think that is a bug, because when I manually update value on protocol_mapper_config table to the client name, then I can see again the info:

view table

view evaluate

Yes, I think it‘s a bug and IIRC there‘s already an issue for it. Most probably it‘s already fixed and will be contained with the next release. But I‘m not 100% sure, a search for the ticket might be useful.

1 Like

I found the reported issue and it was fixed in the version 25.0.2:

issue report

Thanks