Alfresco integration with Active Directory

One of the main features of the Alfresco ECM System is the ability to integrate user authentication and synchronization with Microsoft Active Directory.

Unfortunately, integration is not trivial and it is error prone. While I’ll provide explanations how stuff works you can also have a look at the chapter 6 of the Professional Alfresco: Practical Solutions for Enterprise Content Management (Wrox Programmer to Programmer) [amazon.com] book or to the chapter 4 of the Alfresco 3 Enterprise Content Management Implementation [amazon.com] book.

In this guide I’ll show you how to achieve full integration with Active Directory which includes Alfresco Explorer and Alfresco Share SSO, CIFS SSO, and Active Directory (LDAP) users and groups synchronization.

Prerequisites for this article are: working Active Directory environment, functional basic installation of Alfresco i.e. you can login into working Alfresco using the default admin/admin user. I tend to use bundled Alfresco/Tomcat zip installation since installer can be buggy from version to version and you don’t have full control. I recommend using Alfresco CE 3.2 build 2242 or later since it includes many fixes for NTLM, CIFS and LDAP merged from enterprise version. In my case Alfresco is installed on Windows 2003 EE with SP2 32bit.

Alfresco subsystems

Introduced in version 3.2 are the number of Alfresco subsystems:

  1. Authentication
  2. Synchronization
  3. File Servers
  4. IMAP
  5. sysAdmin
  6. WCM Deployment Receiver
  7. Third party (OpenOffice, Image Magick, etc.)

Subsystems in their nature are separate configurable modules responsible for a sub-part of the Alfresco functionality. Subsystems that we are interested in this article are the first three: authentication, synchronization and file servers. Note that configuration for subsystems is located in their respective folders as shown in the picture:

ScreenShot007

Note that LDAP synchronization is linked to LDAP authentication.

Lets get our hands dirty now.

Authentication

First thing to do to integrate user authentication with Active Directory is to configure the main authentication chain in Alfresco configuration. We do this by adding the following line in \Alfresco\tomcat\shared\classes\alfresco-global.properties:

authentication.chain=passthru1:passthru,ldap-ad1:ldap-ad

Note: ldap-ad is here in chain to support later explained user synchronization.

Now, create the file \subsystems\Authentication\passthru\passthru1\changes.properties and put the following inside:

passthru.authentication.useLocalServer=false
passthru.authentication.servers=DOMAIN\\192.168.0.1,192.168.0.1
ntlm.authentication.sso.enabled=true
alfresco.authentication.allowGuestLogin=false
ntlm.authentication.mapUnknownUserToGuest=false
passthru.authentication.authenticateCIFS=true
passthru.authentication.authenticateFTP=false
passthru.authentication.guestAccess=false
passthru.authentication.defaultAdministratorUserNames=AD_usernames

What we tell Alfresco with the above config is to use the external server for authentication, enable NTLM SSO, and put the list of usernames that should have the administrator role.

Now, edit the \Alfresco\tomcat\shared\classes\alfresco\web-extension\webscript-framework-config-custom.xml file and make sure the following is present and uncommented:

<config evaluator=”string-compare” condition=”Remote”>
<remote>
<!– SSL client certificate + trusted CAs. Optionally used to authenticate share to an external SSO system such as CAS –>
<keystore>
<path>alfresco/web-extension/alfresco-system.p12</path>
<type>pkcs12</type>
<password>alfresco-system</password>
</keystore>
<connector>
<id>alfrescoCookie</id>
<name>Alfresco Connector</name>
<description>Connects to an Alfresco instance using cookie-based authentication</description>
<class>org.alfresco.connector.AlfrescoConnector</class>
</connector>

<endpoint>
<id>alfresco</id>
<name>Alfresco – user access</name>
<description>Access to Alfresco Repository WebScripts that require user authentication</description>
<connector-id>alfrescoCookie</connector-id>
<endpoint-url>http://localhost:8080/alfresco/wcs</endpoint-url>
<identity>user</identity>
<external-auth>true</external-auth>
</endpoint>
</remote>
</config>

Next, edit the WEB-INF\web.xml file found in share.war (hint: share.war is just a zip file with .war extension) and uncomment the following:

<filter>
<filter-name>Authentication Filter</filter-name>
<filter-class>org.alfresco.web.site.servlet.NTLMAuthenticationFilter</filter-class>
<init-param>
<param-name>endpoint</param-name>
<param-value>alfresco</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>Authentication Filter</filter-name>
<url-pattern>/page/*</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>Authentication Filter</filter-name>
<url-pattern>/p/*</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>Authentication Filter</filter-name>
<url-pattern>/s/*</url-pattern>
</filter-mapping>

SSO should now be fully functional for Alfresco Explorer and Alfresco Share. Lets synchronize the users and groups now.

Synchronization

For user synchronization to work we must configure Alfresco to hit the Active Directory domain controller with the appropriate LDAP queries. Queries are highly dependant of ones AD structure so the following configuration covers the scenario where:

  1. All groups that I want in Alfresco are members of a single group called Alfresco Groups,
  2. Users that I want synchronized to Alfresco are members of the above mentioned member groups.

This structure is nice if you have users in different OUs but don’t want them all to be also present in Alfresco.

So, edit the \subsystems\Authentication\ldap-ad\ldap-ad1\changes.properties file and add the following inside:

#
# LDAP Sync
#
# This flag enables use of this LDAP subsystem for authentication. It may be
# that this subsytem should only be used for synchronization, in which case
# this flag should be set to false.
ldap.authentication.active=false
ldap.authentication.java.naming.security.authentication=simple

# This flag enables use of this LDAP subsystem for user and group
# synchronization. It may be that this subsytem should only be used for
# authentication, in which case this flag should be set to false.
ldap.synchronization.active=true
ldap.authentication.userNameFormat=%s
ldap.authentication.allowGuestLogin=true
ldap.authentication.java.naming.provider.url=ldap://domain.local:389

# The default principal to bind with (only used for LDAP sync). This should be a UPN or DN
ldap.synchronization.java.naming.security.principal=user@domain.local

# The password for the default principal (only used for LDAP sync)
ldap.synchronization.java.naming.security.credentials=YourPass

# If positive, this property indicates that RFC 2696 paged results should be
# used to split query results into batches of the specified size. This
# overcomes any size limits imposed by the LDAP server.
ldap.synchronization.queryBatchSize=1000

# The query to select all objects that represent the groups to import.
ldap.synchronization.groupQuery=(&(objectclass\=group)(memberOf\=cn\=Alfresco Groups,ou\=user,dc\=domain,dc\=local))

# The query to select objects that represent the groups to import that have changed since a certain time.
ldap.synchronization.groupDifferentialQuery=(&(objectclass\=group)(memberOf\=cn\=Alfresco Groups,ou\=user,dc\=domain,dc\=local)(!(modifyTimestamp<\={0})))

# The query to select all objects that represent the users to import.
ldap.synchronization.personQuery=(&(objectclass\=user)(|(memberOf\=CN\=Developers,OU\=user,DC\=domain,DC\=local)(memberOf\=CN\=Sales,OU\=user,DC\=domain,DC\=local))(userAccountControl\:1.2.840.113556.1.4.803\:\=512))

# The query to select objects that represent the users to import that have changed since a certain time.
ldap.synchronization.personDifferentialQuery=(&(objectclass\=user)(|(memberOf\=CN\=Developers,OU\=user,DC\=domain,DC\=local)(memberOf\=CN\=Sales,OU\=user,DC\=domain,DC\=local))(userAccountControl\:1.2.840.113556.1.4.803\:\=512)(!(modifyTimestamp<\={0})))

# The group search base restricts the LDAP group query to a sub section of tree on the LDAP server.
ldap.synchronization.groupSearchBase=dc\=domain,dc\=local

# The user search base restricts the LDAP user query to a sub section of tree on the LDAP server.
ldap.synchronization.userSearchBase=dc\=domain,dc\=local

# The name of the operational attribute recording the last update time for a group or user.
ldap.synchronization.modifyTimestampAttributeName=modifyTimestamp

# The timestamp format. Unfortunately, this varies between directory servers.
ldap.synchronization.timestampFormat=yyyyMMddHHmmss’.0Z’

# The attribute name on people objects found in LDAP to use as the uid in Alfresco
ldap.synchronization.userIdAttributeName=sAMAccountName

# The attribute on person objects in LDAP to map to the first name property in Alfresco
ldap.synchronization.userFirstNameAttributeName=givenName

# The attribute on person objects in LDAP to map to the last name property in Alfresco
ldap.synchronization.userLastNameAttributeName=sn

# The attribute on person objects in LDAP to map to the email property in Alfresco
ldap.synchronization.userEmailAttributeName=mail

# The attribute on person objects in LDAP to map to the organizational id  property in Alfresco
ldap.synchronization.userOrganizationalIdAttributeName=company

# The default home folder provider to use for people created via LDAP import
ldap.synchronization.defaultHomeFolderProvider=userHomesHomeFolderProvider

# The attribute on LDAP group objects to map to the gid property in Alfrecso
ldap.synchronization.groupIdAttributeName=cn

# The group type in LDAP
ldap.synchronization.groupType=group

# The person type in LDAP
ldap.synchronization.personType=user

# The attribute in LDAP on group objects that defines the DN for its members
ldap.synchronization.groupMemberAttributeName=member

synchronization.synchronizeChangesOnly=true

What we do above is: disable LDAP authentication and enable just LDAP synchronization, set the LDAP URL to query, credentials with read rights on LDAP, groups query, users query, and LDAP attributes to map Alfresco user’s attributes to. Note that LDAP synchronization is not instant, duration depends on number of objects to synchronize and is scheduled to run every hour (configurable in scheduled-jobs-context.xml).

CIFS

Now, the problematic part. CIFS is usually the hardest one to get it to work properly. So lets start with basic config that should work and then try to fix the eventual problems if there are any.

Edit the \subsystems\fileServers\default\default\changes.properties file and add the following inside:

filesystem.name=Alfresco

filesystem.domainMappings=DOMAIN
filesystem.domainMappings.value.DOMAIN.rangeFrom=192.168.0.0
filesystem.domainMappings.value.DOMAIN.rangeTo=192.168.0.255

cifs.enabled=true
cifs.localname=HOSTNAME
cifs.domain=DOMAIN
cifs.hostannounce=true
cifs.urlfile.prefix=http://hostname:8080/alfresco/

cifs.broadcast=192.168.0.255
cifs.bindto=192.168.0.123
cifs.ipv6=disabled

ftp.enabled=false
ftp.ipv6=disabled
nfs.enabled=false

If it doesn’t work you can try to enable only the Java socket based NetBIOS over TCP/IP. You do this by copying file-servers-context.xml to \subsystems\fileServers\default\default\custom-file-servers-context.xml and commenting out the following sections in it:

<!–
<property name=”netBIOSSMB”>
<bean class=”org.alfresco.filesys.config.NetBIOSSMBConfigBean”>
<property name=”bindTo”>
<value>${cifs.bindto}</value>
</property>
<property name=”sessionPort”>
<value>${cifs.netBIOSSMB.sessionPort}</value>
</property>
<property name=”namePort”>
<value>${cifs.netBIOSSMB.namePort}</value>
</property>
<property name=”datagramPort”>
<value>${cifs.netBIOSSMB.datagramPort}</value>
</property>
<property name=”platforms”>
<value>linux,solaris,macosx</value>
</property>
</bean>
</property>
–>

<!– Use Win32 NetBIOS interface on Windows –>
<!–
<property name=”win32NetBIOS”>
<bean class=”org.alfresco.filesys.config.Win32NetBIOSConfigBean” />
</property>
<property name=”win32HostAnnouncerEnabled”>
<value>${cifs.hostannounce}</value>
</property>
<property name=”win32HostAnnounceInterval”>
<value>5</value>
</property>
–>

Make sure the following property is setup like this:

<!– Use Java socket based NetBIOS over TCP/IP and native SMB on linux –>
<property name=”tcpipSMB”>
<bean class=”org.alfresco.filesys.config.TcpipSMBConfigBean”>
<!–
Can be mapped to non-privileged ports, then use firewall rules to forward requests from the standard
ports
–>
<property name=”port”>
<value>${cifs.tcpipSMB.port}</value>
</property>
<property name=”ipv6Enabled”>
<value>${cifs.ipv6.enabled}</value>
</property>
</bean>
</property>

You must also disable the native SMB over TCP/IP by editing th following registry key:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NetBT\Parameters]
“SMBDeviceEnabled”=dword:00000000

You can also try to disable File and Printer sharing in the network interface’s properties dialog.

Conclusion

As you can see Alfresco integration with Active Directory can be tricky but benefits you get are definitely worth the trouble. If you have any questions feel free to ask them in comments. Feedback is highly appreciated.

You can leave a response, or trackback from your own site.

83 Responses to “Alfresco integration with Active Directory”

  1. marc says:

    Ivan, thx for the great work you done, however user syncing from W2k ad don’t work! I followed your instructions but getting these message in log:

    ERROR [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] Synchronization aborted due to error
    org.alfresco.error.AlfrescoRuntimeException: 03270000 User and group import failed

    Caused by: javax.naming.PartialResultException: Unprocessed Continuation Reference(s); remaining name ‘dc=domain,dc=local’

    WARN [org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer] Failed initial synchronize with user registries
    org.alfresco.error.AlfrescoRuntimeException: 03270000 User and group import failed

    What the heck am I doing wrong?

  2. Mike Iverson says:

    I’m struggling with the “java.text.ParseException: Unparseable date: “20100129023330.0Z” issue as well.

    Does anyone have a fix/cause of this?

  3. Mike Iverson says:

    I solved the problem. My format string had backticks (`), instead of apostrophes (‘).

  4. Sorry for the delay in answering. Apparently I stopped getting notifications about new comments…

    Depends in which security zone is your site. It should log you in automatically if it is placed in Intranet zone. Otherwise, it pops up login window. There is a setting in IE when you click “Custom Level…” at the bottom of the list that controls automatic login in all zones. Other tab will log you in automatically because you’ve already logged in on first tab.

  5. Sorry for the delay in answering. Apparently I stopped getting notifications about new comments…

    Um, have you changed dc=domain,dc=local you match your environment? Other problem could be if you are trying to get results from multiple domains…

  6. Javier says:

    Hello Ivan,

    we have tested this with a 3.2 Community version and it is working fine, but withe the 3.2r Enterprise version, gives an error recovering the groups and users from the AD:

    04260000 user and group import failed

    Do you know which can be the trouble with this?

  7. Javier,

    Can you post entire exception?

  8. Javier says:

    Thank you for your fast reply, this is the exception:

    09:37:26,521 User:System INFO [security.sync.ChainingUserRegistrySynchronizer]
    Synchronizing users and groups with user registry ‘ldap1′
    09:37:26,537 User:System INFO [security.sync.ChainingUserRegistrySynchronizer]
    Retrieving all groups from user registry ‘ldap1′
    09:37:26,599 User:System ERROR [security.sync.ChainingUserRegistrySynchronizer]
    Synchronization aborted due to error
    org.alfresco.error.AlfrescoRuntimeException: 04270000 User and group import fail
    ed
    at org.alfresco.repo.security.sync.ldap.LDAPUserRegistry.processQuery(LD
    APUserRegistry.java:895)
    at org.alfresco.repo.security.sync.ldap.LDAPUserRegistry.getGroups(LDAPU
    serRegistry.java:623)
    at org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer.sync
    WithPlugin(ChainingUserRegistrySynchronizer.java:545)
    at org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer.sync
    hronize(ChainingUserRegistrySynchronizer.java:412)
    at org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer$7.do
    Work(ChainingUserRegistrySynchronizer.java:1251)
    at org.alfresco.repo.security.authentication.AuthenticationUtil.runAs(Au
    thenticationUtil.java:514)
    at org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer.onBo
    otstrap(ChainingUserRegistrySynchronizer.java:1245)
    at org.alfresco.util.AbstractLifecycleBean.onApplicationEvent(AbstractLi
    fecycleBean.java:62)
    at org.springframework.context.event.SimpleApplicationEventMulticaster$1
    .run(SimpleApplicationEventMulticaster.java:77)
    at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecut
    or.java:49)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.m
    ulticastEvent(SimpleApplicationEventMulticaster.java:75)
    at org.springframework.context.support.AbstractApplicationContext.publis
    hEvent(AbstractApplicationContext.java:246)
    at org.springframework.context.support.AbstractApplicationContext.finish
    Refresh(AbstractApplicationContext.java:617)
    at org.springframework.context.support.AbstractApplicationContext.refres
    h(AbstractApplicationContext.java:355)
    at org.alfresco.repo.management.subsystems.ChildApplicationContextFactor
    y$ApplicationContextState.start(ChildApplicationContextFactory.java:637)
    at org.alfresco.repo.management.subsystems.AbstractPropertyBackedBean.st
    art(AbstractPropertyBackedBean.java:454)
    at org.alfresco.repo.management.subsystems.AbstractPropertyBackedBean.on
    ApplicationEvent(AbstractPropertyBackedBean.java:377)
    at org.springframework.context.event.SimpleApplicationEventMulticaster$1
    .run(SimpleApplicationEventMulticaster.java:77)
    at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecut
    or.java:49)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.m
    ulticastEvent(SimpleApplicationEventMulticaster.java:75)
    at org.springframework.context.support.AbstractApplicationContext.publis
    hEvent(AbstractApplicationContext.java:246)
    at org.springframework.context.support.AbstractApplicationContext.finish
    Refresh(AbstractApplicationContext.java:617)
    at org.springframework.context.support.AbstractApplicationContext.refres
    h(AbstractApplicationContext.java:355)
    at org.springframework.web.context.ContextLoader.createWebApplicationCon
    text(ContextLoader.java:246)
    at org.springframework.web.context.ContextLoader.initWebApplicationConte
    xt(ContextLoader.java:189)
    at org.springframework.web.context.ContextLoaderListener.contextInitiali
    zed(ContextLoaderListener.java:49)
    at org.alfresco.web.app.ContextLoaderListener.contextInitialized(Context
    LoaderListener.java:69)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContex
    t.java:3843)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4
    342)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase
    .java:791)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:77
    1)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)

    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.ja
    va:627)
    at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.j
    ava:553)
    at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:488
    )
    at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1149)
    at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java
    :311)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(Lifecycl
    eSupport.java:117)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)

    at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)

    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443
    )
    at org.apache.catalina.core.StandardService.start(StandardService.java:5
    16)
    at org.apache.catalina.core.StandardServer.start(StandardServer.java:710
    )
    at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
    java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
    sorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
    Caused by: javax.naming.PartialResultException: [LDAP: error code 10 – 0000202B:
    RefErr: DSID-031006E0, data 0, 1 access points
    ref 1: ‘abcfotografico.abc’
    ]; remaining name ‘OU=TMI,DC=abcfotografico,DC=abc’
    at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2877)
    at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2794)
    at com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1826)
    at com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1749)
    at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search(ComponentDirCon
    text.java:368)
    at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCom
    positeDirContext.java:338)
    at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCom
    positeDirContext.java:321)
    at javax.naming.directory.InitialDirContext.search(InitialDirContext.jav
    a:248)
    at org.alfresco.repo.security.sync.ldap.LDAPUserRegistry.processQuery(LD
    APUserRegistry.java:883)
    … 50 more
    09:37:26,662 User:System WARN [security.sync.ChainingUserRegistrySynchronizer]
    Failed initial synchronize with user registries
    org.alfresco.error.AlfrescoRuntimeException: 04270000 User and group import fail
    ed
    at org.alfresco.repo.security.sync.ldap.LDAPUserRegistry.processQuery(LD
    APUserRegistry.java:895)
    at org.alfresco.repo.security.sync.ldap.LDAPUserRegistry.getGroups(LDAPU
    serRegistry.java:623)
    at org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer.sync
    WithPlugin(ChainingUserRegistrySynchronizer.java:545)
    at org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer.sync
    hronize(ChainingUserRegistrySynchronizer.java:412)
    at org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer$7.do
    Work(ChainingUserRegistrySynchronizer.java:1251)
    at org.alfresco.repo.security.authentication.AuthenticationUtil.runAs(Au
    thenticationUtil.java:514)
    at org.alfresco.repo.security.sync.ChainingUserRegistrySynchronizer.onBo
    otstrap(ChainingUserRegistrySynchronizer.java:1245)
    at org.alfresco.util.AbstractLifecycleBean.onApplicationEvent(AbstractLi
    fecycleBean.java:62)
    at org.springframework.context.event.SimpleApplicationEventMulticaster$1
    .run(SimpleApplicationEventMulticaster.java:77)
    at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecut
    or.java:49)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.m
    ulticastEvent(SimpleApplicationEventMulticaster.java:75)
    at org.springframework.context.support.AbstractApplicationContext.publis
    hEvent(AbstractApplicationContext.java:246)
    at org.springframework.context.support.AbstractApplicationContext.finish
    Refresh(AbstractApplicationContext.java:617)
    at org.springframework.context.support.AbstractApplicationContext.refres
    h(AbstractApplicationContext.java:355)
    at org.alfresco.repo.management.subsystems.ChildApplicationContextFactor
    y$ApplicationContextState.start(ChildApplicationContextFactory.java:637)
    at org.alfresco.repo.management.subsystems.AbstractPropertyBackedBean.st
    art(AbstractPropertyBackedBean.java:454)
    at org.alfresco.repo.management.subsystems.AbstractPropertyBackedBean.on
    ApplicationEvent(AbstractPropertyBackedBean.java:377)
    at org.springframework.context.event.SimpleApplicationEventMulticaster$1
    .run(SimpleApplicationEventMulticaster.java:77)
    at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecut
    or.java:49)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.m
    ulticastEvent(SimpleApplicationEventMulticaster.java:75)
    at org.springframework.context.support.AbstractApplicationContext.publis
    hEvent(AbstractApplicationContext.java:246)
    at org.springframework.context.support.AbstractApplicationContext.finish
    Refresh(AbstractApplicationContext.java:617)
    at org.springframework.context.support.AbstractApplicationContext.refres
    h(AbstractApplicationContext.java:355)
    at org.springframework.web.context.ContextLoader.createWebApplicationCon
    text(ContextLoader.java:246)
    at org.springframework.web.context.ContextLoader.initWebApplicationConte
    xt(ContextLoader.java:189)
    at org.springframework.web.context.ContextLoaderListener.contextInitiali
    zed(ContextLoaderListener.java:49)
    at org.alfresco.web.app.ContextLoaderListener.contextInitialized(Context
    LoaderListener.java:69)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContex
    t.java:3843)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4
    342)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase
    .java:791)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:77
    1)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)

    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.ja
    va:627)
    at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.j
    ava:553)
    at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:488
    )
    at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1149)
    at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java
    :311)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(Lifecycl
    eSupport.java:117)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)

    at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)

    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443
    )
    at org.apache.catalina.core.StandardService.start(StandardService.java:5
    16)
    at org.apache.catalina.core.StandardServer.start(StandardServer.java:710
    )
    at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
    java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
    sorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
    Caused by: javax.naming.PartialResultException: [LDAP: error code 10 – 0000202B:
    RefErr: DSID-031006E0, data 0, 1 access points
    ref 1: ‘abcfotografico.abc’
    ]; remaining name ‘OU=TMI,DC=abcfotografico,DC=abc’
    at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2877)
    at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2794)
    at com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1826)
    at com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1749)
    at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search(ComponentDirCon
    text.java:368)
    at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCom
    positeDirContext.java:338)
    at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCom
    positeDirContext.java:321)
    at javax.naming.directory.InitialDirContext.search(InitialDirContext.jav
    a:248)
    at org.alfresco.repo.security.sync.ldap.LDAPUserRegistry.processQuery(LD
    APUserRegistry.java:883)
    … 50 more

  9. Javier says:

    Hello again, I have make it work, it is an issue in Alfresco Enterprise 3.2r SP1:

    http://issues.alfresco.com/jira/browse/ALF-2796?page=com.atlassian.jira.plugin.system.issuetabpanels%3Achangehistory-tabpanel

    We have an additional error now, when using CIFS with AD users:

    11:31:45,558 DEBUG [smb.protocol.auth] Using Write transaction
    11:31:45,558 DEBUG [smb.protocol.auth] No PassthruDetails for WNB1
    11:31:45,590 ERROR [smb.protocol.auth] Passthru error getting challenge
    java.lang.NullPointerException
    at org.alfresco.jlan.util.IPAddress.asInteger(IPAddress.java:137)
    at org.alfresco.jlan.server.auth.CifsAuthenticator.mapClientAddressToDom
    ain(CifsAuthenticator.java:958)
    at org.alfresco.filesys.auth.cifs.PassthruCifsAuthenticator.getAuthConte
    xt(PassthruCifsAuthenticator.java:389)
    at org.alfresco.jlan.server.auth.CifsAuthenticator.generateNegotiateResp
    onse(CifsAuthenticator.java:378)
    at org.alfresco.filesys.auth.cifs.PassthruCifsAuthenticator.generateNego
    tiateResponse(PassthruCifsAuthenticator.java:448)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
    java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
    sorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.alfresco.repo.management.subsystems.ChainingSubsystemProxyFactory
    $1.invoke(ChainingSubsystemProxyFactory.java:109)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(
    ReflectiveMethodInvocation.java:171)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynami
    cAopProxy.java:204)
    at $Proxy151.generateNegotiateResponse(Unknown Source)
    at org.alfresco.jlan.smb.server.SMBSrvSession.procSMBNegotiate(SMBSrvSes
    sion.java:1199)
    at org.alfresco.jlan.smb.server.SMBSrvSession.processPacket(SMBSrvSessio
    n.java:1452)
    at org.alfresco.jlan.smb.server.CIFSThreadRequest.runRequest(CIFSThreadR
    equest.java:57)
    at org.alfresco.jlan.server.thread.ThreadRequestPool$ThreadWorker.run(Th
    readRequestPool.java:141)
    at java.lang.Thread.run(Thread.java:619)
    11:31:45,590 DEBUG [smb.protocol.auth] Using Write transaction
    11:31:45,590 DEBUG [smb.protocol.auth] No PassthruDetails for WNB2
    11:32:01,871 ERROR [smb.protocol.auth] Passthru error getting challenge
    java.lang.NullPointerException
    at org.alfresco.jlan.util.IPAddress.asInteger(IPAddress.java:137)
    at org.alfresco.jlan.server.auth.CifsAuthenticator.mapClientAddressToDom
    ain(CifsAuthenticator.java:958)
    at org.alfresco.filesys.auth.cifs.PassthruCifsAuthenticator.getAuthConte
    xt(PassthruCifsAuthenticator.java:389)
    at org.alfresco.jlan.server.auth.CifsAuthenticator.generateNegotiateResp
    onse(CifsAuthenticator.java:378)
    at org.alfresco.filesys.auth.cifs.PassthruCifsAuthenticator.generateNego
    tiateResponse(PassthruCifsAuthenticator.java:448)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
    java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
    sorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.alfresco.repo.management.subsystems.ChainingSubsystemProxyFactory
    $1.invoke(ChainingSubsystemProxyFactory.java:109)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(
    ReflectiveMethodInvocation.java:171)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynami
    cAopProxy.java:204)
    at $Proxy151.generateNegotiateResponse(Unknown Source)
    at org.alfresco.jlan.smb.server.SMBSrvSession.procSMBNegotiate(SMBSrvSes
    sion.java:1199)
    at org.alfresco.jlan.smb.server.SMBSrvSession.processPacket(SMBSrvSessio
    n.java:1452)
    at org.alfresco.jlan.smb.server.CIFSThreadRequest.runRequest(CIFSThreadR
    equest.java:57)
    at org.alfresco.jlan.server.thread.ThreadRequestPool$ThreadWorker.run(Th
    readRequestPool.java:141)
    at java.lang.Thread.run(Thread.java:619)

    Thank you again

  10. It seems that Alfresco can’t map client IP address to a domain name. You could try to comment out domain mappings from CIFS configuration.

  11. Tim says:

    Hi Ivan,

    Thanks alot for the post. I’m having trouble getting this working with Community 3.3. I have followed your instructions as closely as I can, but I am currently stuck with this error:

    ERROR [org.alfresco.fileserver] CIFS server configuration error, Error creating bean with name ‘authenticationComponent’ defined in file [C:\Alfresco\tomcat\webapps\alfresco\WEB-INF\classes\alfresco\subsystems\Authentication\ldap-ad\..\common-ldap-context.xml]: Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type ‘java.lang.String’ to required type ‘boolean’ for property ‘active'; nested exception is java.lang.IllegalArgumentException: Invalid boolean value [${ldap.authentication.active}]

    The error seems to repeat itself down the log file. Perhaps it is somthing I should be posting to Alfresco forum…?

    Cheers!

    Tim.

  12. Article is written for v3.2r2 so it probably needs some minor modifications. On the other hand your error seems to be that ldap.authentication.active is not ‘true’ or ‘false’. Perhaps you’ve got a typo there or something?

  13. Tim says:

    Thanks for the reply, Ivan.

    I can report that there is no typo in the “changes.properties” file in the authentication/ldap-ad/ldap-ad1 directory.

    Your comments therefore led me to question whether it was looking to this file for this information – after playing around it seems that it isn’t. I will take a closer look at why that is the case, but any suggestions off the top of your head would be very welcome? For example, are there any other files we need to copy into the “subsystem” directory structure in the other than the “changes.properties” files? Or any critical configuration settings required to make alfresco look in there which I may have missed?

    Thanks again,

    Tim.

  14. It’s interesting that error is reported by CIFS. Ldap authentication is not supported for CIFS. What does your authentication chain look like? Also can you disable CIFS and then try?

  15. Tim says:

    Authentication chain is as above:
    authentication.chain=passthru1:passthru,ldapad1:ldap-ad

    Disabled CIFS -> no longer getting that error. Looks to have fixed that problem!

    Remaining LDAP query problem, same as Marc above (April 27, 2010 @ 17:16). The error is:
    Caused by: javax.naming.PartialResultException: Unprocessed Continuation Reference(s); remaining name ‘DC=kjrg,DC=local’

    I am pretty sure the query string is right, since I’ve copied it straight out of my ADSI Edit; also not going over multiple domains. Been trying to google an answer to this, hard to find – any thoughts?

    My code:
    # The query to select all objects that represent the groups to import.
    ldap.synchronization.groupQuery=(&(objectclass\=group)(memberOf\=cn\=Alfresco Groups,ou\=Security Groups,ou\=MyBusiness,dc\=kjrg,dc\=local))

    # The query to select objects that represent the groups to import that have changed since a certain time.
    ldap.synchronization.groupDifferentialQuery=(&(objectclass\=group)(memberOf\=cn\=Alfresco Groups,ou\=Security Groups,ou\=MyBusiness,dc\=kjrg,dc\=local)(!(modifyTimestamp<\={0})))

    # The query to select all objects that represent the users to import.
    ldap.synchronization.personQuery=(&(objectclass\=user)(memberOf\=CN\=SBSUsers,OU\=Users,OU\=MyBusiness,DC\=kjrg,DC\=local)(userAccountControl\:1.2.840.113556.1.4.803\:\=512))

    # The query to select objects that represent the users to import that have changed since a certain time.
    ldap.synchronization.personDifferentialQuery=(&(objectclass\=user)(memberOf\=CN\=SBSUsers,OU\=Users,OU\=MyBusiness,DC\=kjrg,DC\=local)(userAccountControl\:1.2.840.113556.1.4.803\:\=512)(!(modifyTimestamp<\={0})))

    # The group search base restricts the LDAP group query to a sub section of tree on the LDAP server.
    ldap.synchronization.groupSearchBase=dc\=kjrg,dc\=local

    # The user search base restricts the LDAP user query to a sub section of tree on the LDAP server.
    ldap.synchronization.userSearchBase=dc\=kjrg,dc\=local

    Tim.

  16. Tim says:

    Sorry…

    Found Javier’s answer above. Solution is to edit the common-ldap-context.xml file to include extra entry key…

    Thanks again Ivan, it’s an exceptionally helpful post!

    Tim.

  17. Tim says:

    Hello again,

    I seem to have it working (can login with AD credentials). The question I now have is: can login be automatic?

  18. Of course. Authentication section of the article describes all required settings. IE should log you in automatically if the site is in Intranet zone (with default settings). Firefox and Mozilla also support the use of NTLM but you need to add the URI to the Alfresco site that you want to access to network.automatic-ntlm-auth.trusted-uris option (available through writing about:config in the URL field) to allow the browser to use your current credentials for login purposes.

  19. Tim says:

    Thanks again for getting back to me, Ivan. I have combed through the post once or twice more (and the web a few times) – just been stuck for the last 5 or so days. What’s going on is:

    * Tomcat console tells me AD sync has worked
    * I can confirm the sync has worked, because in Firefox I can login to Alfresco Explorer (though not Share) with the credentials via the faces.jsp login page, and see the profile info synced.
    * However if I jump into IE it tries to log me in automatically and fails, spitting the Windows 7 credentials dialog. When I enter the password, it always fails – with the Tomcat console reporting the failure.
    * There are obviously other issues with Share, which does not login nor report authentication failures (or attempt to login automatically).

    Given the success of the sync, I assume my LDAP queries are accurate. The thought I had was that perhaps the “ldap.authentication.userNameFormat=%s” was returning an incoherent string for whatever reason. I’ve tried many different permutations of this (including full LDAP query syntax) with no luck.

    Any advice would be very highly valued.

    Cheers,

    Tim.

  20. Tim says:

    Managed to get Alfresco Explorer working, thanks to the following:

    http://forums.alfresco.com/en/viewtopic.php?f=9&t=16794

    I needed to make the group policy setting for NTLM authentication recommended in this post.

    Still cannot get Share going – am continuing to work through all the information on the web for something I’ve missed.

  21. Curtis says:

    Ivan, I appreciate your documentation too. Thanks. I’m running CE3.3 and so far this is the best explanation I’ve seen.

    In the examples you’ve provided above it would be helpful if I knew which settings needed to be set specifically for my domain. It’s obvious that some of the entries must be changed (IP addresses, etc.) but I’m uncertain about some of the others.

    Can you give us (newbies) a little more info on the settings that are site-specific? Thanks in advance!

  22. Hi Curtis,
    thanks for feedback.

    I’m preparing a new guide for version 3.3g and I’ll try to highlight those custom sections. New article will be more up to date and also simplify some stuff and have some corrections.

    As for now, I can give you a quick list:
    passthru.authentication.servers=DOMAIN\\192.168.0.1,192.168.0.1
    passthru.authentication.defaultAdministratorUserNames=AD_usernames

    ldap.authentication.java.naming.provider.url=ldap://domain.local:389
    ldap.synchronization.java.naming.security.principal=user@domain.local
    ldap.synchronization.java.naming.security.credentials=YourPass
    ldap.synchronization.groupQuery=
    ldap.synchronization.groupDifferentialQuery=
    ldap.synchronization.personQuery=
    ldap.synchronization.personDifferentialQuery=
    ldap.synchronization.groupSearchBase=dc\=domain,dc\=local
    ldap.synchronization.userSearchBase=dc\=domain,dc\=local

    filesystem.domainMappings=DOMAIN
    filesystem.domainMappings.value.DOMAIN.rangeFrom=192.168.0.0
    filesystem.domainMappings.value.DOMAIN.rangeTo=192.168.0.255

    cifs.localname=HOSTNAME
    cifs.domain=DOMAIN
    cifs.urlfile.prefix=http://hostname:8080/alfresco/

    cifs.broadcast=192.168.0.255
    cifs.bindto=192.168.0.123

    I hope this helps!

  23. […] last article on Alfresco integration with Active Directory brought up a lot of interest and what’s the most important positive feedback. That article is […]

  24. Nondu says:

    Hi Ivan

    Hi Ivan
    Thanks for the article. I followed the instruction I’m using alfresco 3.3.1 and it gave me this error “net.sf.acegisecurity.AuthenticationServiceException: Failed to open passthru auth session” can you please help me.

  25. Steven says:

    Hi all

    I want to thank you about this guide, it’s helping me a lot,’cause this is the first time that try to install alfresco, but i’ve some doubts about this lines:

    # The query to select all objects that represent the groups to import.
    ldap.synchronization.groupQuery=(&(objectclass\=group)(memberOf\=cn\=Alfresco Groups,ou\=user,dc\=domain,dc\=local))

    # The query to select objects that represent the groups to import that have changed since a certain time.
    ldap.synchronization.groupDifferentialQuery=(&(objectclass\=group)(memberOf\=cn\=Alfresco Groups,ou\=user,dc\=domain,dc\=local)(!(modifyTimestamp<\={0})))

    # The query to select all objects that represent the users to import.
    ldap.synchronization.personQuery=(&(objectclass\=user)(|(memberOf\=CN\=Developers,OU\=user,DC\=domain,DC\=local)(memberOf\=CN\=Sales,OU\=user,DC\=domain,DC\=local))(userAccountControl\:1.2.840.113556.1.4.803\:\=512))

    # The query to select objects that represent the users to import that have changed since a certain time.
    ldap.synchronization.personDifferentialQuery=(&(objectclass\=user)(|(memberOf\=CN\=Developers,OU\=user,DC\=domain,DC\=local)(memberOf\=CN\=Sales,OU\=user,DC\=domain,DC\=local))(userAccountControl\:1.2.840.113556.1.4.803\:\=512)(!(modifyTimestamp<\={0})))

    i really don get wich values do i have to change by mines, so i'd apreciate the help
    and i want to apologize (i know my english it's crappy).
    thnx!

  26. Hi Steven,

    glad you find this guide helpful. You basically need to change above queries to match your organization. You query LDAP for users and groups that you want in Alfresco. How to write LDAP queries is really beyond this article and I’m sure that there are great tutorials available on other sites which you could use, with my example queries, to write ones for your environment.

    Regards

  27. Steven says:

    Ivan, thnx for the reply, and i want you to know, that the others guides aren’t this helpful, i have changed the values, but the sync shows me this:

    log4j:ERROR Failed to rename [alfresco.log] to [alfresco.log.2010-11-02].
    00:00:00,617 User:System WARN [security.sync.ChainingUserRegistrySynchronizer]
    Full synchronization with user registry ‘ldap1′; some users and groups previousl
    y created by synchronization with this user registry may be removed.
    00:00:00,633 User:System INFO [security.sync.ChainingUserRegistrySynchronizer]
    Retrieving all groups from user registry ‘ldap1′
    00:00:00,648 User:System INFO [security.sync.ChainingUserRegistrySynchronizer]
    ldap1 Group Analysis: Commencing batch of 0 entries
    00:00:00,648 User:System INFO [security.sync.ChainingUserRegistrySynchronizer]
    ldap1 Group Analysis: Completed batch of 0 entries
    00:00:00,695 User:System INFO [security.sync.ChainingUserRegistrySynchronizer]
    Retrieving all users from user registry ‘ldap1′
    00:00:00,711 User:System INFO [security.sync.ChainingUserRegistrySynchronizer]
    ldap1 User Creation and Association: Commencing batch of 0 entries
    00:00:00,711 User:System INFO [security.sync.ChainingUserRegistrySynchronizer]
    ldap1 User Creation and Association: Completed batch of 0 entries
    00:00:00,711 User:System INFO [security.sync.ChainingUserRegistrySynchronizer]
    ldap1 Authority Deletion: Commencing batch of 0 entries
    00:00:00,711 User:System INFO [security.sync.ChainingUserRegistrySynchronizer]
    ldap1 Authority Deletion: Completed batch of 0 entries
    00:00:00,711 User:System INFO [security.sync.ChainingUserRegistrySynchronizer]
    Finished synchronizing users and groups with user registry ‘ldap1′
    00:00:00,711 User:System INFO [security.sync.ChainingUserRegistrySynchronizer]
    0 user(s) and 0 group(s) processed

    i hope you can help me again.

    regards.

  28. niox says:

    Hi guys,

    Can i use this config for alfresco 3.4?
    I need AD connection and ntlm.

  29. Brazen says:

    I used this config for Alfresco 3.4d against a Windows 2008 R2 domain. It works, but none of the imported groups have users added to them. The users are members of the groups in Active Directory but when they are imported in to Alfresco, no users are members of any groups.

    Do users get put in their groups with the import in Alfresco 3.3g? I would go back to that version, if it would work correctly.

  30. I’d rathet double-check the config. Empty groups usually indicate faulty LDAP query than version problems.

  31. Brian says:

    I seem to be having problems with this so I hope you can help.
    My issue is that it doesn’t appear to be pulling the name or email from AD as expected. For some reason, “givenName” is pulling the username instead of the users First Name as expected, sn is pulling null and mail is pulling null. We are running Windows Server 2003 if that makes a difference.
    Any help would be greatly appreciated.

  32. Priscila says:

    Hello! I have a question on the integration of Alfresco with AD. I’m using version 5.0.d. At the university what stage do I use 3 OU’s (Students, Staff and Teachers) We can create a “Alfresco Group” and put it all users or have to create another “OU Alfresco”?

  33. admin says:

    Hi,

    That really depends on your AD policies. I’m not sure “OU Alfresco” fits your scenario as you can’t have users/groups in two different OUs at the same time. What Alfresco does is that it runs a LDAP query to find all groups from AD that you need to import and that will become Alfresco groups, and then it runs a LDAP query to import users. It is irrelevant if users are in the same groups in AD however if they are they will be mapped to the same groups in Alfresco i.e. you can import users that won’t be a part of any group.

    So all you need is to get those two LDAP queries to return exactly what you want from AD, for example all groups that are in some OU, or all groups that are members of a top level group, or you can use DN LDAP attribute of groups to pinpoint exact group names which can be in different OUs and don’t have a common parent group. In other words, for a group query you need (&(objectclass=group)(WHATEVER)) where WHATEVER represents a valid LDAP query that will return a proper list of groups that you need. Some LDAP query tool like Sysinternals AD Explorer can be of great help here to get the LDAP query right and test things a lot faster then rebooting Alfresco many times.

    Regards


Leave a Reply