How to get user roles in access token

what I am trying to do:

  1. I have an app that takes in login credentials: username and password for a user. I have a rest api that internally calls the keycloak REST API: /auth/realms/realmname/protocol/openid-connect/token and gets the access token for this user.
  2. Now I am building another REST API to access a resource where I want to do the following: doSomething(accesstoken, data){a) call keycloak API to validate access token and get roles. b) if role == manager, process(data)c) else: return error msg.}

Now, how do I do (a): validating the access token and getting the roles associated with it. I know we can do:

auth/realms/realmname/protocol/openid-connect/userinfo

but that only gives the details about the user like name, email, etc. but does not display any roles. Here’s an example I got:

{
    "name": "test user",
    "sub": "e2bad34d-a1a9-4d70-ac84-bd3a3246023e",
    "email_verified": false,
    "preferred_username": "user",
    "given_name": "test",
    "family_name": "user"
}

As seen, it doesnt give the roles at all. How do I then tell what roles this access token has? Interestingly, when I search for this, many resources are suggesting the above userinfo endpoint. But this merely tells me taht the access token I provided is valid. Does not give roles for that. In other words - it authenticates but does not authorize.

Please suggest.

Thanks, Anand

Usually Keycloak OIDC client has assigned default roles scope, where all roles related mappers (e.g. client/realm role mappers) are configured. So you can modify those mappers in that scope to “publish” data also to userinfo output. Or you can configure those mappers on the client level as well. Of course you need to be sure that user has assigned some roles.

Hi,

You could also use the introspect endpoint, it will return the roles and whether the user is active or not

curl -v \
http://localhost:8180/auth/realms/demo/protocol/openid-connect/token/introspect \
-H 'cache-control: no-cache' \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'client_id=crn-user-ldap&client_secret=d8d0....e5&token=eyJhbGc...Bxw'

This is an output example:
"jti":"c98d59b9-c6c5-455b-a0d6- b7bcca50b59c","exp":1545886929,"nbf":0,"iat":1545886629,"iss":"http://localhost:8180/auth/realms/demo","aud":"crn-user-ldap","sub":"9a4ce56b-028a-4fb8-8f4c-db1ef5c800b9","typ":"Bearer","azp":"crn-user-ldap","auth_time":0,"session_state":"d336cacd-2ba6-49e4-bd89-836de43b2275","name":"demo user","given_name":"demo","family_name":"user","preferred_username":"demouser1","email":"demouser@haventec.com","acr":"1","allowed-origins":[],"realm_access":{"roles":["uma_authorization"]},"resource_access":{"account":{"roles":["manage-account","manage-account-links","view-profile"]}},"client_id":"crn-user-ldap","username":"demouser1","active":true}

Thanks! I had to set the mappers correctly for the client. Once done, this worked

Hello @happyCoder1980, can you please share your implementation. I’m stock on the same issue

I’m using the easy way to fold the roles into an id token. All you need is the keycloak admin console. Come into your realm. Next → Client sopes → roles and you get to the Settings tab. There enable “Include in token scope”. Next, go to the Mappers tab on the same page. There you need “realm roles” - go in there and include all “ADD” as well, do the same with “client roles” in the same Mappers tab After that all roles will be stacked as claims in your id token and on the backend you can read them from claims of Principal class or same classes which is also a lot to read token in Spring Boot Security.

1 Like