[keycloak-user] Having trouble with LDAP attribute mapping in 1.3.1

Marek Posolda mposolda at redhat.com
Fri Jun 19 10:22:17 EDT 2015


Ouch, this is a bug:-(

Feel free to create JIRA.

The UserModel in Keycloak DB has each attribute modelled as one string 
value. But I think I can address it with the usage of some delimiter and 
then for access token has the protocol mapper, which will handle it.

So for example if your LDAP user has 3 values of attribute 
"applications" with values "finance", "sales", "development", the 
attribute on the Keycloak UserModel will have value like 
"finance###sales###development" (The sequence ### will be used as 
delimiter), but for the access token it will be divided again. So in 
your application, you will have possibility to have something like:

Set<String> applications = 
accessToken.getOtherClaims().getAttribute("applications");

which will return set with 3 values "finance", "sales", "development".

Marek

On 19.6.2015 15:22, Kevin Thorpe wrote:
> Ok, I think I understand. I tried 'sync all users' and got an error. 
> Is this because applications is a multiple
> attribute? Obviously I will probably have access to more than one 
> application. In the meantime I'll try a brand
> new user and see if that works.
>
> Log shows:
>
> 2015-06-19 14:19:26,361 INFO 
>  [org.keycloak.federation.ldap.LDAPFederationProviderFactory] (default 
> task-2) Sync all users from LDAP to local store: realm: master, 
> federation provider: PI  ordinary users
> 2015-06-19 14:19:26,611 ERROR [io.undertow.request] (default task-2) 
> UT005023: Exception handling request to 
> /auth/admin/realms/master/user-federation/instances/141db483-1f5c-412f-acbb-0ea642015798/sync: 
> java.lang.RuntimeException: request path: 
> /auth/admin/realms/master/user-federation/instances/141db483-1f5c-412f-acbb-0ea642015798/sync
>         at 
> org.keycloak.services.filters.KeycloakSessionServletFilter.doFilter(KeycloakSessionServletFilter.java:54)
>         at 
> io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
>         at 
> io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132)
>         at 
> io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:85)
>         at 
> io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
>         at 
> io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
>         at 
> org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
>         at 
> io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
>         at 
> io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
>         at 
> io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
>         at 
> io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
>         at 
> io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
>         at 
> io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
>         at 
> io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58)
>         at 
> io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:72)
>         at 
> io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
>         at 
> io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76)
>         at 
> io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
>         at 
> org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
>         at 
> io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
>         at 
> io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
>         at 
> io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:274)
>         at 
> io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:253)
>         at 
> io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:80)
>         at 
> io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:172)
>         at 
> io.undertow.server.Connectors.executeRootHandler(Connectors.java:199)
>         at 
> io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:774)
>         at 
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
>         at 
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
>         at java.lang.Thread.run(Thread.java:745)
> Caused by: org.jboss.resteasy.spi.UnhandledException: 
> java.lang.ClassCastException: java.util.TreeSet cannot be cast to 
> java.lang.String
>         at 
> org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:76)
>         at 
> org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:212)
>         at 
> org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:149)
>         at 
> org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:372)
>         at 
> org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:179)
>         at 
> org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:220)
>         at 
> org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
>         at 
> org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
>         at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
>         at 
> io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:86)
>         at 
> io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:130)
>         at 
> org.keycloak.services.filters.ClientConnectionFilter.doFilter(ClientConnectionFilter.java:41)
>         at 
> io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
>         at 
> io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132)
>         at 
> org.keycloak.services.filters.KeycloakSessionServletFilter.doFilter(KeycloakSessionServletFilter.java:40)
>         ... 29 more
> Caused by: java.lang.ClassCastException: java.util.TreeSet cannot be 
> cast to java.lang.String
>         at 
> org.keycloak.federation.ldap.mappers.UserAttributeLDAPFederationMapper.onImportUserFromLDAP(UserAttributeLDAPFederationMapper.java:60)
>         at 
> org.keycloak.federation.ldap.LDAPFederationProvider.importLDAPUsers(LDAPFederationProvider.java:404)
>         at 
> org.keycloak.federation.ldap.LDAPFederationProviderFactory.importLdapUsers(LDAPFederationProviderFactory.java:269)
>         at 
> org.keycloak.federation.ldap.LDAPFederationProviderFactory$1.run(LDAPFederationProviderFactory.java:223)
>         at 
> org.keycloak.models.utils.KeycloakModelUtils.runJobInTransaction(KeycloakModelUtils.java:241)
>         at 
> org.keycloak.federation.ldap.LDAPFederationProviderFactory.syncImpl(LDAPFederationProviderFactory.java:219)
>         at 
> org.keycloak.federation.ldap.LDAPFederationProviderFactory.syncAllUsers(LDAPFederationProviderFactory.java:177)
>         at 
> org.keycloak.services.managers.UsersSyncManager.syncAllUsers(UsersSyncManager.java:50)
>         at 
> org.keycloak.services.resources.admin.UserFederationProviderResource.syncUsers(UserFederationProviderResource.java:144)
>         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>         at 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
>         at 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>         at java.lang.reflect.Method.invoke(Method.java:497)
>         at 
> org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:137)
>         at 
> org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:296)
>         at 
> org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:250)
>         at 
> org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:140)
>         at 
> org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:109)
>         at 
> org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:135)
>         at 
> org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:109)
>         at 
> org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:135)
>         at 
> org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:109)
>         at 
> org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:135)
>         at 
> org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:103)
>         at 
> org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:356)
>         ... 40 more
>
>
> *Kevin Thorpe
> *
> CTO
>
> <https://www.p-i.net/> <https://twitter.com/@PI_150>
>
> www.p-i.net <http://www.p-i.net/> | @PI_150 <https://twitter.com/@PI_150>
>
> M: +44 (0)7425 160 368 | T: +44 (0)203 005 6750 | F: +44(0)207 730 2635
> 150 Buckingham Palace Road, London, SW1W 9TR, UK
>
> **
> _____________________________
>
> This email and any files transmitted with it are confidential and 
> intended solely for the use of the individual or entity to whom they 
> are addressed. If you have received this email in error please notify 
> the system manager. This message contains confidential information and 
> is intended only for the individual named. If you are not the named 
> addressee you should not disseminate, distribute or copy this e-mail. 
> Please notify the sender immediately by e-mail if you have received 
> this e-mail by mistake and delete this e-mail from your system. If you 
> are not the intended recipient you are notified that disclosing, 
> copying, distributing or taking any action in reliance on the contents 
> of this information is strictly prohibited.
>
> *"SAVE PAPER - THINK BEFORE YOU PRINT!" *
>
>
> On 19 June 2015 at 13:50, Marek Posolda <mposolda at redhat.com 
> <mailto:mposolda at redhat.com>> wrote:
>
>     Thanks for the info. Now I think I know what's going on.
>
>     The issue is that currently when we import users from LDAP
>     (federation in general), we sync the configured attributes to the
>     Keycloak DB. But during searching, we don't sync the attributes
>     from LDAP to Keycloak DB anymore. So I guess you did the steps
>     like this:
>     - You first authenticate as LDAP user "joe" (or search this user
>     from admin console), which imported this user into Keycloak DB
>     - Then you created mapper for the 'applications' attribute. But
>     user 'joe' was already imported into Keycloak DB from the previous
>     step, right?
>
>     I believe that when you import some other user from LDAP, which is
>     not yet exist in Keycloak DB, the 'applications' attribute will be
>     there. For the existing user, the only possibility right now is to
>     use "Synchronize all users" or "Synchronize changed users" on LDAP
>     federation screen. This will update existing users into Keycloak
>     DB as well, so 'joe' will be updated.
>
>     Please let me know if it helps.  Looks that it's something we
>     should address better in Keycloak.
>
>     Marek
>
>
>     On 19.6.2015 11:56, Kevin Thorpe wrote:
>>     I had a hunch so I added a record in USER_ATTRIBUTE for
>>     applications and it is getting passed
>>     in the JWT claims now. That squarely points at the ldap
>>     federation part.
>>
>>     *Kevin Thorpe
>>     *
>>     CTO
>>
>>     <https://www.p-i.net/> <https://twitter.com/@PI_150>
>>
>>     www.p-i.net <http://www.p-i.net/> | @PI_150
>>     <https://twitter.com/@PI_150>
>>
>>     M: +44 (0)7425 160 368 | T: +44 (0)203 005 6750 | F: +44(0)207
>>     730 2635
>>     150 Buckingham Palace Road, London, SW1W 9TR, UK
>>
>>     **
>>     _____________________________
>>
>>     This email and any files transmitted with it are confidential and
>>     intended solely for the use of the individual or entity to whom
>>     they are addressed. If you have received this email in error
>>     please notify the system manager. This message contains
>>     confidential information and is intended only for the individual
>>     named. If you are not the named addressee you should not
>>     disseminate, distribute or copy this e-mail. Please notify the
>>     sender immediately by e-mail if you have received this e-mail by
>>     mistake and delete this e-mail from your system. If you are not
>>     the intended recipient you are notified that disclosing, copying,
>>     distributing or taking any action in reliance on the contents of
>>     this information is strictly prohibited.
>>
>>     *"SAVE PAPER - THINK BEFORE YOU PRINT!" *
>>
>>
>>     On 19 June 2015 at 10:42, Kevin Thorpe <kevin.thorpe at p-i.net
>>     <mailto:kevin.thorpe at p-i.net>> wrote:
>>
>>         Hi Marek, thanks for the quick reply.
>>
>>         1. I am definitely sure that the attributes I need are in the
>>         LDAP record.
>>
>>         2. adding trace to federation.ldap shows my mapped attributes
>>         being read
>>
>>         3. there is no USER_ATTRIBUTES table I'm assuming you meant
>>         USER_ATTRIBUTE but it doesn't have my attributes.
>>            it does have a reference to my LDAP_ID so i8t looks like
>>         it should be here
>>
>>         MariaDB [keycloak]> select * from USER_ATTRIBUTE;
>>         +---------+-------------------------------------+--------------------------------------+
>>         | NAME    | VALUE         | USER_ID          |
>>         +---------+-------------------------------------+--------------------------------------+
>>         | LDAP_ID | 7fc89601-96e711e2-a5a7b2a9-738d4470 |
>>         471f0b4f-cb7c-4610-b3d6-ddd3a18e9986 |
>>         | LDAP_ID | 3245fc81-55c211e2-a5a7b2a9-738d4470 |
>>         6d64f5a2-d356-4ab6-9b4d-3f89a3ee38c4 |
>>         +---------+-------------------------------------+--------------------------------------+
>>
>>         thanks for your time on this
>>
>>         *Kevin Thorpe
>>         *
>>         CTO
>>
>>         <https://www.p-i.net/> <https://twitter.com/@PI_150>
>>
>>         www.p-i.net <http://www.p-i.net/> | @PI_150
>>         <https://twitter.com/@PI_150>
>>
>>         M: +44 (0)7425 160 368 | T: +44 (0)203 005 6750 | F:
>>         +44(0)207 730 2635
>>         150 Buckingham Palace Road, London, SW1W 9TR, UK
>>
>>         **
>>         _____________________________
>>
>>         This email and any files transmitted with it are confidential
>>         and intended solely for the use of the individual or entity
>>         to whom they are addressed. If you have received this email
>>         in error please notify the system manager. This message
>>         contains confidential information and is intended only for
>>         the individual named. If you are not the named addressee you
>>         should not disseminate, distribute or copy this e-mail.
>>         Please notify the sender immediately by e-mail if you have
>>         received this e-mail by mistake and delete this e-mail from
>>         your system. If you are not the intended recipient you are
>>         notified that disclosing, copying, distributing or taking any
>>         action in reliance on the contents of this information is
>>         strictly prohibited.
>>
>>         *"SAVE PAPER - THINK BEFORE YOU PRINT!" *
>>
>>
>>         On 19 June 2015 at 10:15, Marek Posolda <mposolda at redhat.com
>>         <mailto:mposolda at redhat.com>> wrote:
>>
>>             There are few steps here and the result will work only if
>>             all steps success. So it might help to try which step
>>             could be wrong here:
>>
>>             1) You can doublecheck if your user really has
>>             'applications' attribute in LDAP
>>
>>             2) If (1) is ok, you can enable TRACE logging for
>>             "org.keycloak.federation.ldap" category in standalone.xml
>>             . With it, you should see some trace messages with the
>>             names and values of all LDAP attributes, which are loaded
>>             in user record. You should see the 'applications'
>>             attribute loaded
>>
>>             3) If (2) is ok, you can browse keycloak database and
>>             check if attribute 'applications' is really here. The
>>             user attributes are saved in table USER_ATTRIBUTES.
>>             Currently it's not possible to browse user attributes
>>             generically in admin console (unless you do custom theme)
>>             so browse DB seems to be the only possibility.
>>
>>             4) If (3) is ok, the issue is not in LDAP interaction,
>>             but in protocol mapper configuration. Make sure you use
>>             correct protocol mapper (In your case it should be "User
>>             attributes" mapper, not "User property" mapper). Also if
>>             your application is Java based, the value of
>>             'applications' claim is saved in accessToken in
>>             'otherClaims' map and can be retrieved with something
>>             like: accessToken.getOtherClaims().get("applications");
>>
>>             Marek
>>
>>
>>
>>             On 18.6.2015 17:50, Kevin Thorpe wrote:
>>>             Thanks to the team for 1.3.1. We were eagerly waiting
>>>             for that to add LDAP attribute mappings which I see has
>>>             now been done. Unfortunately I can't seem to get it to work.
>>>
>>>             I have added a user attribute mapper to my ldap
>>>             federation. This maps the LDAP atribute 'applications'
>>>             which exists on my LDAP user record to 'applications' in
>>>             Keycloak.
>>>
>>>             I have also added a user attribute token mapper to my
>>>             Keycloak client definition to map user attribute
>>>             'applications' to token claim 'applications'. I've also
>>>             asked to add to both id and access token.
>>>
>>>             However this attribute is not present in either the ID
>>>             or access token when testing. Is there something I've
>>>             missed?
>>>
>>>             Something that may be an issue though is that I'm using
>>>             a home written openid-connect Lua client based on your
>>>             javascript one. This uses the endpoint
>>>             /auth/realms/master/protocol/openid-connect/token. Is it
>>>             that the openid-connect endpoint doesn't support these
>>>             attributes yet?
>>>
>>>             *Kevin Thorpe
>>>             *
>>>             CTO, PI ltd
>>>
>>>
>>>             _______________________________________________
>>>             keycloak-user mailing list
>>>             keycloak-user at lists.jboss.org  <mailto:keycloak-user at lists.jboss.org>
>>>             https://lists.jboss.org/mailman/listinfo/keycloak-user
>>
>>
>>
>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/keycloak-user/attachments/20150619/e7061280/attachment-0001.html 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: image/jpeg
Size: 3053 bytes
Desc: not available
Url : http://lists.jboss.org/pipermail/keycloak-user/attachments/20150619/e7061280/attachment-0004.jpe 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: image/jpeg
Size: 1204 bytes
Desc: not available
Url : http://lists.jboss.org/pipermail/keycloak-user/attachments/20150619/e7061280/attachment-0005.jpe 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: image/jpeg
Size: 3053 bytes
Desc: not available
Url : http://lists.jboss.org/pipermail/keycloak-user/attachments/20150619/e7061280/attachment-0006.jpe 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: image/jpeg
Size: 1204 bytes
Desc: not available
Url : http://lists.jboss.org/pipermail/keycloak-user/attachments/20150619/e7061280/attachment-0007.jpe 


More information about the keycloak-user mailing list