Category Archives: Authentication

Best Practices for Using Active Directory with Alfresco

Normally when I help a user that involves issues with setting up synchronization of users and groups, the customer has settings that are extremely generic like these:

ldap.synchronization.groupSearchBase=dc\=example,dc\=foo
ldap.synchronization.userSearchBase=dc\=example,dc\=foo

ldap.synchronization.groupQuery=objectclass\=group
ldap.synchronization.personQuery=(&(objectclass\=user)(userAccountControl\:1.2.840.113556.1.4.803\:\=512))

ldap.synchronization.personDifferentialQuery=(&(objectclass\=user)(userAccountControl\:1.2.840.113556.1.4.803\:\=512)(!(modifyTimestamp<\={0})))
ldap.synchronization.groupDifferentialQuery=(&(objectclass\=group)(!modifyTimestamp<\={0}))

Syntactically speaking, these queries are fine but they synch users and groups from a very naive perspective. What these queries and settings are telling you are this:

1. We’ll start our search for groups and users in example.foo (based on the settings below).

ldap.synchronization.groupSearchBase=dc\=example,dc\=foo
ldap.synchronization.userSearchBase=dc\=example,dc\=foo

2. We will synch in ALL users and ALL groups inside of example.foo.

ldap.synchronization.groupQuery=objectclass\=group
ldap.synchronization.personQuery=(&(objectclass\=user)(userAccountControl\:1.2.840.113556.1.4.803\:\=512))

3. When the differential synchronization occurs we will synch in any additional users and groups that are created that fit the query we’ve set up previously (which to say will be ALL of them).

ldap.synchronization.personDifferentialQuery=(&(objectclass\=user)(userAccountControl\:1.2.840.113556.1.4.803\:\=512)(!(modifyTimestamp<\={0})))
ldap.synchronization.groupDifferentialQuery=(&(objectclass\=group)(!modifyTimestamp<\={0}))

Now, you may have a use-case that requires this but that’s probably not likely. Almost more likely is the fact that most of your AD users will not be using Alfresco. A lot of them maybe but not all of them. The best practice here is to create an Alfresco organizational unit and then create a couple of different Alfresco groups in this OU:

Create an Alfresco organizational unit with a distinguished name like so:

OU=Alfresco,DC=example,DC=foo

Then you can create any Alfresco specific groups underneath OU=Alfresco like so:

CN=AlfrescoAdmins,OU=Alfresco,DC=example,DC=foo
CN=AlfrescoUsers,OU=Alfresco,DC=example,DC=foo

At this point, you can assign your users to these different two groups. For my testing purposes I created 3 AD users (aduser1, aduser2, aduser3) and then made aduser1 a member of AlfrescoAdmins and then all three, members of AlfrescoUsers. Now we can change our queries to look thusly:

Our LDAP queries will now only search for groups in ou=Alfresco,dc=example,dc=foo and users throughout the directory (as they could realistically exist in many places).

ldap.synchronization.groupSearchBase=ou\=alfresco,dc\=example,dc\=foo
ldap.synchronization.userSearchBase=dc\=example,dc\=foo

We can keep at least the groupQuery the same. This will bring in every group in OU=Alfresco:

ldap.synchronization.groupQuery=objectclass\=group

This will only bring in users who are members of AlfrescoAdmins and AlfrescoUsers and not every single user in Active Directory:

ldap.synchronization.personQuery=(&(objectclass\=user)(userAccountControl\:1.2.840.113556.1.4.803\:\=512)(|(memberOf=cn\=AlfrescoAdmins,ou=alfresco,dc=example,dc=foo)(memberOf=cn\=AlfrescoUsers,ou=alfresco,dc=example,dc=foo)))

Next of course, for differential synchs we’ll use the same queries except add the modifiedTimestamp directive at the end:

ldap.synchronization.personDifferentialQuery=(&(objectclass\=user)(userAccountControl\:1.2.840.113556.1.4.803\:\=512)(|(memberOf=cn\=AlfrescoAdmins,ou=alfresco,dc=example,dc=foo)(memberOf=cn\=AlfrescoUsers,ou=alfresco,dc=example,dc=foo))(!(modifyTimestamp<\={0})))

ldap.synchronization.groupDifferentialQuery=(&(objectclass\=group)(!modifyTimestamp<\={0}))

Below are the LDAP and Synchronization settings I used for 4.2.x and this works with no issues:

### AD authentication only ###
authentication.chain=alfrescoNtlm1:alfrescoNtlm,ldap-ad1:ldap-ad
ldap.authentication.active=true
ldap.authentication.allowGuestLogin=true
ldap.authentication.userNameFormat=%s@example.foo
ldap.authentication.java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
ldap.authentication.java.naming.provider.url=ldap://example.foo:389
ldap.authentication.java.naming.security.authentication=simple
ldap.authentication.escapeCommasInBind=false
ldap.authentication.escapeCommasInUid=false
ldap.authentication.defaultAdministratorUserNames=Administrator

ldap.synchronization.active=true
ldap.synchronization.java.naming.security.principal=administrator@example.foo
ldap.synchronization.java.naming.security.credentials=Alfr3sc0
ldap.synchronization.queryBatchSize=1000
ldap.synchronization.attributeBatchSize=1000
synchronization.synchronizeChangesOnly=false
synchronization.allowDeletions=true
synchronization.syncWhenMissingPeopleLogIn=true

ldap.synchronization.groupQuery=objectclass\=group
ldap.synchronization.groupDifferentialQuery=(&(objectclass\=group)(!(modifyTimestamp<\={0})))

ldap.synchronization.personQuery=(&(objectclass\=user)(userAccountControl\:1.2.840.113556.1.4.803\:\=512)(|(memberOf=cn\=AlfrescoAdmins,ou=alfresco,dc=example,dc=foo)(memberOf=cn\=AlfrescoUsers,ou=alfresco,dc=example,dc=foo)))

ldap.synchronization.personDifferentialQuery=(&(objectclass\=user)(userAccountControl\:1.2.840.113556.1.4.803\:\=512)(|(memberOf=cn\=AlfrescoAdmins,ou=alfresco,dc=example,dc=foo)(memberOf=cn\=AlfrescoUsers,ou=alfresco,dc=example,dc=foo))(!(modifyTimestamp<\={0})))

ldap.synchronization.groupSearchBase=ou\=alfresco,dc\=example,dc\=foo

ldap.synchronization.userSearchBase=dc\=example,dc\=foo

ldap.synchronization.modifyTimestampAttributeName=modifyTimestamp
ldap.synchronization.timestampFormat=yyyyMMddHHmmss'.0Z'
ldap.synchronization.userIdAttributeName=sAMAccountName
ldap.synchronization.userFirstNameAttributeName=givenName
ldap.synchronization.userLastNameAttributeName=sn
ldap.synchronization.userEmailAttributeName=mail
ldap.synchronization.userOrganizationalIdAttributeName=company
ldap.synchronization.defaultHomeFolderProvider=largeHomeFolderProvider
ldap.synchronization.groupIdAttributeName=cn
ldap.synchronization.groupDisplayNameAttributeName=displayName
ldap.synchronization.groupType=group
ldap.synchronization.personType=user
ldap.synchronization.groupMemberAttributeName=member
ldap.synchronization.enableProgressEstimation=true

Now all groups show up and all users show up in the proper group. I hope this is helpful.

-H.S.