52

In my rest service i can obtain the principal information after authentication using

KeycloakPrincipal kcPrincipal = (KeycloakPrincipal) servletRequest.getUserPrincipal();

statement.

Keycloak principal doesn't contain all the information i need about the authenticated user. Is it possible to customize my own principal type? On the keycloak-server-end I've developed a user federation provider. I saw that UserModel makes possible to add a set of custom attributes to my user.

Is it possible to insert my custom principal in that code?

Is it possible to retrieve this attributes from keycloak principal?

What is the way?

Chris K
  • 347
  • 1
  • 3
  • 16
Alex
  • 1,515
  • 2
  • 22
  • 44
  • http://stackoverflow.com/questions/29014894/obtaining-user-roles-in-servlet-application-using-keycloak – Vítor Sep 29 '15 at 00:52

3 Answers3

93

To add custom attributes you need to do three things:

  1. Add attributes to admin console
  2. Add claim mapping
  3. Access claims

The first one is explained pretty good here: https://www.keycloak.org/docs/latest/server_admin/index.html#user-attributes

Add claim mapping:

  1. Open the admin console of your realm.
  2. Go to Clients and open your client
  3. This only works for Settings > Access Type confidential or public (not bearer-only)
  4. Go to Mappers
  5. Create a mapping from your attribute to json
  6. Check "Add to ID token"

Access claims:

final Principal userPrincipal = httpRequest.getUserPrincipal();

if (userPrincipal instanceof KeycloakPrincipal) {

    KeycloakPrincipal<KeycloakSecurityContext> kp = (KeycloakPrincipal<KeycloakSecurityContext>) userPrincipal;
    IDToken token = kp.getKeycloakSecurityContext().getIdToken();

    Map<String, Object> otherClaims = token.getOtherClaims();

    if (otherClaims.containsKey("YOUR_CLAIM_KEY")) {
        yourClaim = String.valueOf(otherClaims.get("YOUR_CLAIM_KEY"));
    }
} else {
    throw new RuntimeException(...);
}

I used this for a custom attribute I added with a custom theme.

starball
  • 20,030
  • 7
  • 43
  • 238
lisa p.
  • 2,138
  • 21
  • 36
  • I can able to retrieve email id,GivenName,Family Name.But unable to retrieve custom attribute mobile .I'm getting OtherClaims with size 0. – Surya Movva Oct 12 '17 at 13:43
  • My code is: KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) request. getUserPrincipal(); KeycloakPrincipal principal = (KeycloakPrincipal) token.getPrincipal(); IDToken idToken = principal.getKeycloakSecurityContext().getIdToken(); System.err.println("size "+otherClaims.size()+idToken.getEmail()+idToken.getFamilyName()); – Surya Movva Oct 12 '17 at 13:51
  • @SuryaMovva, have you added the mappings in keycloak administration console under the client you are using? – Turbut Alin Oct 25 '17 at 18:56
  • @TurbutAlin Hi. I have the same problem. I cant see new attributes added to the user. I have added the mapping under my client (spring boot app) and still no new attributes are received. Could you please help? Thanks – troger19 Dec 06 '17 at 13:26
  • Link is outdated, correct one is https://www.keycloak.org/docs/latest/server_admin/index.html#user-attributes – lkamal Oct 09 '18 at 18:16
  • idToken is alway null for me. i do get an access token. i can't figure out what i don't have right. suggestions? – denov Dec 19 '21 at 20:28
70
  • Select Users > Lookup > click on ID > go to attributes tab > Add attribute > e.g.: phone > Save enter image description here

  • Select Clients > click on Client ID > go to Mappers Tab > create mapper

    enter image description here

    enter image description here

    enter image description here

  • Get custom attributes

    enter image description here

    enter image description here

UPDATE

  • Add 'phone' attribute on Group level, assign user to that group, and you get 'phone' attribute from group level for all users

  • Go back to mapper and update 'phone' with 'Aggregate attribute values = true' and 'Multivalued=true', and you get 'phone' as list with both attributes from group and user level. If you keep 'Aggregate attribute values = false' or 'Multivalued=false', you get just one value, where 'phone' attribute from user will override 'phone' attribute from group (which make sense)

Dmitri Algazin
  • 3,332
  • 27
  • 30
Neeraj Benjwal
  • 1,271
  • 10
  • 10
  • 8
    Thanks @Neeraj I was doing the same things you just posted. The problem on my side was the cache. After the mapping or user attribute is added, I need to clean the realm cache in Keycloak admin console. Afterwards I was able to see the attributes in otherClaims too. Hope this helps eerybody. – troger19 Dec 07 '17 at 12:37
  • 1
    @troger19 Thank you for this comment, I spent hours upon hours because I didn't think of that. – Neikius Dec 18 '17 at 17:06
  • 2
    Thank you for the solution. Is there a way to apply the custom attributes to all users? I specifically need to do this for all of my users that are imported through my Ldap provider. – user1026498 Mar 02 '18 at 20:46
  • Thanks for solution! Did what we wanted! Updated your answer with group attributes options – Dmitri Algazin Jul 17 '19 at 15:00
  • I'm new to KeyCloak and am using latest ver 6.0.1. Your answer was such a God send - clear, concise and correct! Thanks. Kudos!! – sunitkatkar Aug 04 '19 at 19:01
  • @Neeraj For mobile app I want to keep device_id , device_model , latitude and longtitude when I login via RESTAPI (/openid-connect/token). Keycloak support it? – Panup Pong Aug 26 '19 at 09:37
6

For Keycloak > 18 the configuration of the mappers has moved in the UI:

Inside Clients > Your selected client under the tab Client Scopes, one has to select account-dedicated:

enter image description here

There custom mappers can be added:

enter image description here

Stefan
  • 1,151
  • 1
  • 8
  • 13