Monday, April 2, 2012

How to Use LDAP with CQ / AEM

Use case: Configure LDAP with CQ / AEM

Why There are some changes in LDAP configuration in CQ5.5 and documetation is still in progress. Before actual documentation comes, Here is few things you should know

Pre requisite Keep http://dev.day.com/docs/en/cq/current/core/administering/ldap_authentication.html on side. I will mention things changed.

No sample_ldap_login.conf under crx-quickstart\server\etc : In fact there is no crx-quickstart\server\etc. You can put your sample_ldap_login.conf any where you want. You can get sample ldap.conf from http://dev.day.com/content/kb/home/cq5/CQ5SystemAdministration/LdapConfig.html or here

2) Once downloaded you can put this file to any location (I prefer /crx-quickstart/conf) and then change your start script to point to this location.

3) I have seen, LDAP not starting because of some wrong configuration in repository.xml. Also attaching sample repository.xml that you can use directly in CQ5.5 / CRX2.3

How to enable logging for LDAP in CQ5.5 / CQ5.6
1) Note that LDAP module is now deployed as OSGI module. You have to follow following step to enable logging for LDAP

[1] Log into Felix Console: http://<host>:<port>/system/console/configMgr
[2] From "Factory Configurations", create "Apache Sling Logging Writer Configuration"
[2.1] Set value of "Log File" to "../logs/ldap.log"
[2.2] Click on "Save"
[3] From "Factory Configurations", create "Apache Sling Logging Logger Configuration"
[3.1] Set value of "Log Level" to "Debug"
[3.2] Set value of "Log File" to "../logs/ldap.log"
[3.3] Add "Logger" => com.day.crx.security.ldap
[3.4] Click on "Save"

Step [2] is require for log rotation, If you don't want to rotate log then skip that step.

user purge and sync option In CQ5.5 GA release, there is no user purge and sync option. This is moved to JMX. This option is now available as CQ5.5 Update Package 1, That you can download it from package share. To use this option, Please install CQ5.5 Update 1, Start CQ with LDAP enable and then go to Felix JMX console. You would see something like this



Full path in JVM Param I have seen issues with some customer where using relative path for ldap.conf file does not work. Please use complete path of file system instead.

Change in start script: CQ5.5 OOTB has options enabled for jass config. You can use following environment variable to enable LDAP through start script

CQ_USE_JAAS='true'
CQ_JAAS_CONFIG='< Complete Path to LDAP conf file>'

See how it is used in start script

if [ $CQ_USE_JAAS ]; then
START_OPTS="${START_OPTS} -Djava.security.auth.login.config=${CQ_JAAS_CONFIG}"

Secure LDAP Password:

http://helpx.adobe.com/experience-manager/kb/encrypted-password-jaas-config.html

One more interesting Blog http://www.citytechinc.com/us/en/blog/2012/03/adobe_cq5_5_and_ldap.html

Hope fully all changes are covered. Shoot me any question if it is not clear for LDAP with CQ5.5.


Configure LDAP in CQ / AEM6

In CQ6 All login module can be configured as Pluggable Login Module. What that mean is there is no need to create JAAS config through start up param. You can configure your LDAP using OSGI config. Steps of how to do that can be found from

http://docs.adobe.com/docs/en/aem/6-0/administer/security/ldap-config.html

How to create OSGI config can be found from here http://www.wemblog.com/2012/10/how-to-work-with-configurations-in-cq.html

this is how sample LDAP config will look like in AEM6 (Here custom can be any thing)

/apps
 /yourcompany
   /configurations
       /config.author
         /org.apache.jackrabbit.oak.security.authentication.ldap.impl.LdapIdentityProvider-custom.xml
         /org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncHandler-custom.xml
         /org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModuleFactory-custom.xml


Here is how content of these file look like,

1) org.apache.jackrabbit.oak.security.authentication.ldap.impl.LdapIdentityProvider-custom.xml

There are more attribute as well please read above documentation for that.

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
    jcr:primaryType="sling:OsgiConfig"
    provider.name="custom_ldap"
    host.name="server-name"
    host.port="server-port"
    bind.dn="same as authDn"
    bind.password="same as password"
    user.baseDN="same as userRoot"
    user.idAttribute="same as userIdAttribute"
    user.extraFilter="same as userFilter"
    group.baseDN="same as groupRoot"

    group.extraFilter="same as groupFilter"/>

2) org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncHandler-custom.xml

following property could defer based on your LDAP.

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
    jcr:primaryType="sling:OsgiConfig"
    handler.name="custom_ldap_handler"
    user.expirationTime="1d"
    user.autoMembership="[any CQ group]"
    user.propertyMapping="[rep:email=mail,rep:fullName=cn,profile/email=mail,profile/familyName=sn,profile/givenName=gn]"
    user.membershipExpTime="1d"
    group.propertyMapping="[description=description,rep:email=mail,rep:fullname=cn]"
    />

3) org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModuleFactory-custom.xml

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
  xmlns:jcr="http://www.jcp.org/jcr/1.0" 
  jcr:primaryType="sling:OsgiConfig"
  jaas.controlFlag="REQUIRED"
  idp.name="custom_ldap" 
  sync.handlerName="custom_ldap_handler" />






30 comments:

  1. Are multiple ldap directories supported?

    ReplyDelete
    Replies
    1. Please refer http://dev.day.com/content/kb/home/Crx/CrxSystemAdministration/HowToMultipleLdapServer.html for multiple LDAP directory

      Delete
    2. Yogesh,

      Thanks! It seems to change with versions of CRX, and I was hoping that how it was done in 2.2 was how it is still done in 2.3, and it appears to be that way.

      Delete
    3. One for CRX2.2 .. should work for CRX2.3 as well ..

      Delete
  2. I'm getting the following error:

    Service Unavailable
    AuthenticationSupport service missing. Cannot authenticate request.

    Any ideas on how to troubleshoot?

    ReplyDelete
    Replies
    1. Yes. Please enable Logging for LDAP. If nothing is getting printed in log that mean there is something wrong with LDAP.conf file or repository.xml.

      Delete
  3. Hi Yogesh,

    Is there any required to do this configuation other than a cq instance ?

    ReplyDelete
    Replies
    1. @ Anonymous,

      Sorry did not understand your question. Can you please elaborate ?

      Delete
  4. I have followed above steps and used attached files .
    On hitting url http://localhost:4502
    I'm getting the following error:

    Service Unavailable
    AuthenticationSupport service missing. Cannot authenticate request.

    on checking logs
    21.05.2012 18:33:49.035 *ERROR* [FelixStartLevel] org.apache.jackrabbit.core.DefaultSecurityManager Neither JAAS nor RepositoryConfig contained a valid configuration for com.day.crx


    any idea where i am doing wrong ?

    ReplyDelete
    Replies
    1. @Anonymous,

      That means your LDAP is not configured properly. Make sure that you get some message in ldap log when you enable debugging. You can also try manually starting CQ with param, Instead of using start script. If even that does not help, Create a daycare ticket and some one would be able to help.

      Delete
  5. Yogesh,
    What is your take on the scalability of the users and groups implementation in CQ? Can this support Ldap synchronization of say upto million users? Is there any volumetrics shared by Adobe?
    Regards,
    Deepak

    ReplyDelete
    Replies
    1. Deepak,

      There is no limit on number of users or group but there is limit on number of nodes you can have under one node (Avoid Flat hierarchy), before your system become slow. I guess in order to make changes in child node, parent node also needs to be bring in memory and hence more thrashing and slow performance.

      http://wiki.apache.org/jackrabbit/Performance

      http://people.apache.org/~jukka/jackrabbit/report-2011-09-01/report.html

      Yogesh

      Delete
    2. This comment has been removed by the author.

      Delete
  6. Hi,

    I'm getting the following error after a login with correct credentials (authentication works):

    java.lang.IllegalArgumentException: Invalid token ''
    at org.apache.jackrabbit.api.security.authentication.token.TokenCredentials.(TokenCredentials.java:42)
    at com.day.crx.security.token.impl.TokenAuthenticationHandler.createCredentials(TokenAuthenticationHandler.java:528)
    at com.day.crx.security.token.impl.TokenAuthenticationHandler.extractCredentials(TokenAuthenticationHandler.java:345)
    at org.apache.sling.auth.core.impl.AuthenticationHandlerHolder.doExtractCredentials(AuthenticationHandlerHolder.java:75)
    at org.apache.sling.auth.core.impl.AbstractAuthenticationHandlerHolder.extractCredentials(AbstractAuthenticationHandlerHolder.java:60)
    Truncated. see log file for complete stacktrace


    Any ideas on how to troubleshoot?

    ReplyDelete
    Replies
    1. Robert,

      Looks like there is some invalid character in the login name. You can enable debugging on TokenAuthentication Handler module to find out more information.

      Yogesh

      Delete
    2. The issue is that the first login attempt which creates the account does not get a CRX Login Token.

      If you delete the login cookie for the nascent account and try logging in a second time it will work and get a CRX Login Token.

      Delete
    3. Tokens are stored in the user's home directory jcr node tree.

      There is no home directory jcr node tree for an LDAP user that has never logged in. Autocreate mode specifies that the account is created on demand including the home directory.

      If the user's LDAP CN is Adams\, Alice
      and LDAP sAMAccountName is A-Adams

      Then on the first login, autocreate causes these nodes to be created

      /home/users/Adams\, Alice/A-Adams
      /home/users/Adams\, Alice/A-Adams/profile
      /home/users/Adams\, Alice/A-Adams/rep:policy
      /home/users/Adams\, Alice/A-Adams/rep:policy/allow

      What is not created is:

      /home/users/Adams\, Alice/A-Adams/.tokens

      I think that the routine that creates the .tokens node is executed prior to the one that creates the parent node of .tokens (in this case /home/users/Adams\, Alice/A-Adams). The result is that it fails to create the .tokens node.

      The second LDAP login works, the home directory already exists and the .tokens node is created.

      Delete
    4. If your LDAP account contains upper case letters an attempt to log in the first time without matching the case exactly triggers this bug.

      Delete
    5. This was patched by Adobe but I'm not sure if the patch made it into a release. We have been running with a hotfix for some time now.

      Delete
  7. Hi, can someone help me in getting last login date of a user in CQ5 please

    ReplyDelete
    Replies
    1. I would recommend to create a node under user profile as soon as user login with login date. Reset every time user logs in again. For this you might have to create custom login module http://dev.day.com/docs/en/crx/current/deploying/custom-login-modules.html. Also note that as soon as user logs in a token is created for that user under /home/users//.tokens/ but this is not reliable.

      Delete
  8. Hi Yogesh,

    i have connected CQ55 with OpenDS directory server. CQ55 is able to communicate with the LDAP server but CQ is not fetching all the user or groups from LDAP server. Only after I login to CQ, the user and user related group is being fetched by CQ.

    Is there any explicit settings I need to provide. Please help.

    ReplyDelete
    Replies
    1. Abani,

      This is how LDAP login works. Only after login you would be able to get user related information. If you want to prefetch all data in advance please use user sync option as mentioned above. Please let me know if that make sense.

      Yogesh

      Delete
    2. Hi Yogesh,

      Thanks for your reply. I have tried with the user sync option available through JMX. But, this option only pulls the information of the users who are available in CRX. It doesn't fetch all the users from LDAP. below I have given the jaas.conf file details. Can you please validate the same & let me know if the configuration is good enough.


      com.day.crx {
      com.day.crx.core.CRXLoginModule sufficient;
      com.day.crx.security.ldap.LDAPLoginModule required
      principal_provider.class="com.day.crx.security.ldap.principals.LDAPPrincipalProvider"
      host="localhost"
      port="389"
      secure="FALSE"
      trust_credentials_attribute="TrustedInfo"
      authDn="cn=**********"
      authPw="*******"
      userRoot="ou=users,dc=example,dc=com"
      groupRoot="ou=groups,dc=example,dc=com"
      groupMembershipAttribute="uniquemember"
      groupNameAttribute="cn"
      userFilter="(objectclass=inetorgPerson)"
      groupFilter="(objectclass=groupOfUniqueNames)"
      autocreate="create"
      autocreate.user.nodetype="rep:user"
      autocreate.group.nodetype="rep:group"
      autocreate.user.mail="profile/email"
      autocreate.user.givenname="profile/givenname"
      autocreate.user.sn="profile/familyName"
      autocreate.user.telephoneNumber="profile/telephoneNumber"
      autocreate.user.memberof="profile/memberof"
      autocreate.syncdelay="0"
      autocreate.group.description="description"
      autocreate.group.cn="profile/fullname"
      autocreate.path="direct"
      cache.expiration="600"
      searchTimeout="60000"
      cache.maxsize="100";
      };

      Regards,
      Abani

      Delete
    3. Abani,

      Ideally LDAP sync should sync all data, If not I would suggest to open a daycare ticket for that. Also you can create your own custom login module using http://www.wemblog.com/2012/06/how-to-add-custom-login-module-in-cq55.html to sync data from your LDAP.

      Yogesh

      Delete
  9. Hi, i'm trying to use the LDAP User Synchronization functionality in CQ5.5 (http://wem.help.adobe.com/enterprise/en_US/10-0/core/administering/ldap_authentication.html#LDAP User Synchronization) but i can not find the ldap entry inside 'Repository Configuration' to configure the list of DN to import. Am i missing something? Thanks!

    ReplyDelete
    Replies
    1. Sebastian,

      What Version of CQ are you using ? If you are using CQ 5.5 note that you need SP2.1 inorder to see that option. You can get SP2.1 from Daycare or public package share.

      Yogesh

      Delete
  10. Hi Yogesh,

    I'm trying to implement the LDAP feature in CQ5.5. I've installed service pack 2 and restarted the system, but I'm unable to find granite.ldap in "JMX" felix console? is ldap exist in SP 2? or do i need to install SP 1 ?

    Thanks!
    Ganesh

    ReplyDelete
  11. Hi Yogesh,

    we are using AEM6 and Author able to login with LDAP Username and password without any issues but if author forget the password we are able to reset the password in AEM6 using Password rest option and unable to store the Latest password in LDAP server.

    Is there any Class or API available to do the authorization and authendication to update the latest password in LDAP via AEM server.

    Please advise.

    Thanks,
    Raj

    ReplyDelete
    Replies
    1. Hi Yogesh/Britto Raj,

      We were trying to integrate LDAP with AEM6 for Author and we are getting the following error after LDAP Authentication: java.lang.IllegalArgumentException: Invalid token ''

      Any idea why would it be? Appreciate your response.

      Thanks,
      Samod

      Delete