Hello Dmitry,
thank you for your reply.
I developed my keycloak spi based on keycloak-quickstarts/user-storage-jpa, but this
project is two years old. The getAttribute in this project looks like my implementation:
@Override
public List<String> getAttribute(String name) {
if (name.equals("phone")) {
List<String> phone = new LinkedList<>();
phone.add(entity.getPhone());
return phone;
} else {
return super.getAttribute(name);
}
}
In case of a missing attribute this method returns a null value and then a Null Pointer
Exception is thrown. I think the keycloak code should be fixed to avoid NPE or at least
the example should be changed. Anyway this works for me:
@Override
public List<String> getAttribute(String name) {
final List<String> values;
if (attributes.containsKey(name)) {
values = attributes.get(name);
} else {
values = super.getAttribute(name);
}
return Optional.ofNullable(values).orElse(Collections.emptyList());
}
Thanks,
Lorenzo
Il giorno 1 feb 2019, alle ore 19:10, Dmitry Telegin
<dt(a)acutus.pro> ha scritto:
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