[keycloak-user] Not existent attributes for users from user-federeation cause NPE

Dmitry Telegin dt at acutus.pro
Fri Feb 1 13:10:55 EST 2019


Hello Lorenzo,

Out of interest I've tried to play with keycloak-quickstarts/user-storage-simple. I was able to authenticate as "tbrady" even though its UserModel obviously returns null from getAttribute(). But in this case KeycloakModelUtils::resolveAttribute() is invoked not on the UserModel supplied by the provider, but rather on o.k.models.cache.infinispan.UserAdapter wrapper (which performs null checking and returns an empty list in that case). Not sure why resolveAttribute is invoked on your UserAdapter directly, but I think it's safe to return an empty list too.

Did you try keycloak-quickstarts/user-storage-jpa by the way?

Cheers,
Dmitry Telegin
CTO, Acutus s.r.o.
Keycloak Consulting and Training

Pod lipami street 339/52, 130 00 Prague 3, Czech Republic
+42 (022) 888-30-71
E-mail: info at acutus.pro

On Fri, 2019-02-01 at 16:54 +0100, Lorenzo Luconi Trombacchi wrote:
> I’m using Keycloak version 4.8.3 with a custom user federation plugin. I created a new realm, configured my user federation plugin and created a new client. I tried to authenticate and I got an error 500 from keycloak.
> In Keycloak log I found this NullPointerException:
> 
> 14:09:15,472 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (default task-1) Uncaught server error: java.lang.NullPointerException
> >  	at org.keycloak.models.utils.KeycloakModelUtils.resolveAttribute(KeycloakModelUtils.java:414)
> >  	at org.keycloak.models.utils.KeycloakModelUtils.resolveAttribute(KeycloakModelUtils.java:415)
> >  	at org.keycloak.protocol.oidc.mappers.UserAttributeMapper.setClaim(UserAttributeMapper.java:93)
> >  	at org.keycloak.protocol.oidc.mappers.UserAttributeMapper.setClaim(UserAttributeMapper.java:101)
> >  	at org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper.setClaim(AbstractOIDCProtocolMapper.java:117)
> >  	at org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper.setClaim(AbstractOIDCProtocolMapper.java:119)
> >  	at org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper.transformAccessToken(AbstractOIDCProtocolMapper.java:81)
> >  	at org.keycloak.protocol.oidc.TokenManager.transformAccessToken(TokenManager.java:606)
> >  	at org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper.transformAccessToken(AbstractOIDCProtocolMapper.java:81)
> >  	at org.keycloak.protocol.oidc.TokenManager.createClientAccessToken(TokenManager.java:422)
> >  	at org.keycloak.protocol.oidc.TokenManager$AccessTokenResponseBuilder.generateAccessToken(TokenManager.java:795)
> >  	at org.keycloak.protocol.oidc.TokenManager.transformAccessToken(TokenManager.java:544)
> >  	at org.keycloak.protocol.oidc.endpoints.TokenEndpoint.resourceOwnerPasswordCredentialsGrant(TokenEndpoint.java:569)
> >  	at org.keycloak.protocol.oidc.endpoints.TokenEndpoint.processGrantRequest(TokenEndpoint.java:186)
> >  	at org.keycloak.protocol.oidc.TokenManager.createClientAccessToken(TokenManager.java:402)
> …..
> 
> After some tests I found the problem: the “Assigned Default Client Scopes” list, in my newly created client, includes the “profile” scope. 
> The “profile” scope includes a lot of attributes and not all of them are exported from my federation plugin for my users. Removing profile scope solve the problem and now I can successfully authenticate my federeted users.
> 
> In class KeycloakModelUtils  the are two implementation of the method resolveAttribute:
> 
>     public static List<String>  resolveAttribute(GroupModel group, String name) {
>         List<String> values = group.getAttribute(name);
>         if (values != null && !values.isEmpty()) return values;
>         if (group.getParentId() == null) return null;
>         return resolveAttribute(group.getParent(), name);
> 
>     }
> 
> 
>     public static Collection<String> resolveAttribute(UserModel user, String name, boolean aggregateAttrs) {
>         List<String> values = user.getAttribute(name);
>         Set<String> aggrValues = new HashSet<String>();
>         if (!values.isEmpty()) {
>             if (!aggregateAttrs) {
>                 return values;
>             }
>             aggrValues.addAll(values);
>         }
>         for (GroupModel group : user.getGroups()) {
>             values = resolveAttribute(group, name);
>             if (values != null && !values.isEmpty()) {
>                 if (!aggregateAttrs) {
>                     return values;
>                 }
>                 aggrValues.addAll(values);
>             }
>         }
>         return aggrValues;
>     }
> 
> 
> As you can see the first implementation checks if values is null, but not the second one where I got NPE.
> 
> In my UserModel implementation I override the getAttrubute method:
> 
> public class UserAdapter extends AbstractUserAdapterFederatedStorage {
> 
> …..
>     @Override
>     public List<String> getAttribute(String name) {
>         if (attributes.containsKey(name)) {
>             return attributes.get(name);
>         }
> 
>         return super.getAttribute(name);
>     }
> 
> }
> 
> 
> If I force this method to return an empty list instead of null value, this solve the problem. Is this the right fix? getAttribute method must not returns a null value?
> 
> 
> I hope this helps.
> 
> Thanks,
> Lorenzo
> 
> 
> 
> 
> 
> _______________________________________________
> keycloak-user mailing list
> keycloak-user at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/keycloak-user


More information about the keycloak-user mailing list