'Accessing keycloak roles / users attributes from Java API

I've created a role and and a user in Keycloak and added one attribute in both of them; for example:

my_role_attr = 'x'
my_user_attr = 'y'

Then I'm trying to access that info. via the JAVA KeycloakSecurityContext (and the associated AccessToken / IDToken). I can see the name of the roles and the user information but I cannot find those attributes.

I understand that I've to creat a Protocol Mapper "User Attribute" to map the "my_user_attr" into a Token Claim. Then it's fine I can get the value in the AccessToken / IDToken.

But I cannot find a way to get the role attribute. I do not see any "Protocol Mapper" for role attribute. Am I missing something.



Solution 1:[1]

I have been trying to do the same thing; and it is not easy, however you can use the script mapper with some success. The source code at https://github.com/keycloak/keycloak/blob/master/server-spi/src/main/java/org/keycloak/models/RoleModel.java has some useful information. This SO item (thank you Andre B) also has useful information How to create a Script Mapper in Keycloak?.

My (not perfect or complete) solution is:

/**
 * Available variables: 
 * user - the current user
 * realm - the current realm
 * token - the current token
 * userSession - the current userSession
 * keycloakSession - the current userSession
 */


var roles = [];
var client = keycloakSession.getContext().getClient();
user.getClientRoleMappings(client).forEach(function(roleModel) {
    var attr = [];
    var names = {};
    var rn = roleModel.getName();
    var map = roleModel.getAttributes();
    map.forEach(function(key, value){
        var k = {};
        var a = false;
        value.forEach(function(l){
            a = (l === 'true');
        });
        k[key] = a;
        attr.push(k);
    });
    names[rn] = attr;
    roles.push(names);
});


exports = roles;

Note that you probably need to set 'Multivalued' to "ON" and the 'Claim JSON Type' to "Select One..".

Solution 2:[2]

A more generic answer should be

var roles = [];
var client = keycloakSession.getContext().getClient();
user.getRoleMappings().forEach(function(roleModel) {
    
    var attr = {};
    var names = {};
    var rn = roleModel.getName();
    var map = roleModel.getAttributes();
    map.forEach(function(key, value){
        attr[key] = value;
    }); 
    roles[rn] = attr;
});

exports = roles;

to export roles' attributes like

"Role1": {
      "key1": [
        "Values1"
      ],
      "key2": [
        "values2"
      ]
    }

Solution 3:[3]

No, you are not missing something. It is just not implemented. However, there is a feature request. You may want to watch and vote up KEYCLOAK-17418.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Peter
Solution 2 mikiqex
Solution 3 mikiqex