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(a)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(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/keycloak-user