This describes how to authenticate against Active Directory with multiple OU's with Shibboleth version 3.2.1, specifically 1 AD server (or 2 mirrored servers) with 4 OU's. The LDAP documentation suggests to connect to multiple OU's you can use idp.authn.LDAP.userFilter=(&(|(ou:dn:=people)(ou:dn:=guests))(uid={user})) but unfortunately thats not supported by Active Directory.
Step-by-step guide
Add another authenticator to ldap-authn-config.xml
<!-- Active Directory Configuration for 1 server with 4 OU's -->
<bean id="adAuthenticator" class="org.ldaptive.auth.Authenticator" p:authenticationResponseHandlers-ref="authenticationResponseHandler"
p:resolveEntryOnFailure="%{idp.authn.LDAP.resolveEntryOnFailure:false}">
<constructor-arg index="0" ref="formatDnResolver" />
<constructor-arg index="1" ref="authHandler" />
</bean>
<bean id="authenticationResponseHandler" class="org.ldaptive.auth.ext.ActiveDirectoryAuthenticationResponseHandler" />
<!-- Define Directory1 connection pool -->
<bean id="adConnectionPool" class="org.ldaptive.pool.BlockingConnectionPool" abstract="true"
p:blockWaitTime="%{idp.pool.LDAP.blockWaitTime:3000}"
p:poolConfig-ref="adPoolConfig"
p:pruneStrategy-ref="adPruneStrategy"
p:validator-ref="adSearchValidator"
p:failFastInitialize="%{idp.pool.LDAP.failFastInitialize:false}" />
<bean id="adPoolConfig" class="org.ldaptive.pool.PoolConfig"
p:minPoolSize="%{idp.pool.LDAP.minSize:3}"
p:maxPoolSize="%{idp.pool.LDAP.maxSize:10}"
p:validateOnCheckOut="%{idp.pool.LDAP.validateOnCheckout:false}"
p:validatePeriodically="%{idp.pool.LDAP.validatePeriodically:true}"
p:validatePeriod="%{idp.pool.LDAP.validatePeriod:300}" />
<bean id="adPruneStrategy" class="org.ldaptive.pool.IdlePruneStrategy"
p:prunePeriod="%{idp.pool.LDAP.prunePeriod:300}"
p:idleTime="%{idp.pool.LDAP.idleTime:600}" />
<bean id="adSearchValidator" class="org.ldaptive.pool.SearchValidator" />
<!-- Directory1 connection pool settings -->
<bean id="adConnectionConfig" class="org.ldaptive.ConnectionConfig" abstract="true"
p:ldapUrl="%{idp.authn.LDAP.ldapURL}"
p:useStartTLS="%{idp.authn.LDAP.useStartTLS:true}"
p:useSSL="%{idp.authn.LDAP.useSSL:false}"
p:connectTimeout="%{idp.authn.LDAP.connectTimeout:3000}"
p:sslConfig-ref="adSslConfig" />
<alias name="%{idp.authn.LDAP.sslConfig:certificateTrust}" alias="adSslConfig" />
<!-- ldap.properties "idp.authn.LDAP.authenticator = adAggregateAuthenticator" -->
<bean id="adAggregateAuthenticator" class="org.ldaptive.auth.Authenticator"
p:authenticationResponseHandlers-ref="adAuthenticationResponseHandler">
<constructor-arg index="0" ref="adAggregateDnResolver" />
<constructor-arg index="1" ref="adAggregateAuthHandler" />
</bean>
<bean id="adAuthenticationResponseHandler" class="org.ldaptive.auth.ext.ActiveDirectoryAuthenticationResponseHandler" />
<bean id="adAggregateDnResolver" class="org.ldaptive.auth.AggregateDnResolver">
<constructor-arg index="0" ref="adDnResolvers" />
</bean>
<bean id="adAggregateAuthHandler" class="org.ldaptive.auth.AggregateDnResolver$AuthenticationHandler"
p:authenticationHandlers-ref="adAuthHandlers" />
<util:map id="adDnResolvers">
<entry key="directory_filter1" value-ref="adDnResolver1" />
<entry key="directory_filter2" value-ref="adDnResolver2" />
<entry key="directory_filter3" value-ref="adDnResolver3" />
<entry key="directory_filter4" value-ref="adDnResolver4" />
</util:map>
<!-- Define four DN resolvers that bind search against the Directory -->
<bean id="adDnResolver1" class="org.ldaptive.auth.PooledSearchDnResolver"
p:baseDn="%{idp.authn.LDAP.baseDN1}"
p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"
p:userFilter="%{idp.authn.LDAP.userFilter}"
p:connectionFactory-ref="adBindSearchPooledConnectionFactory" />
<bean id="adDnResolver2" class="org.ldaptive.auth.PooledSearchDnResolver"
p:baseDn="%{idp.authn.LDAP.baseDN2}"
p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"
p:userFilter="%{idp.authn.LDAP.userFilter}"
p:connectionFactory-ref="adBindSearchPooledConnectionFactory" />
<bean id="adDnResolver3" class="org.ldaptive.auth.PooledSearchDnResolver"
p:baseDn="%{idp.authn.LDAP.baseDN3}"
p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"
p:userFilter="%{idp.authn.LDAP.userFilter}"
p:connectionFactory-ref="adBindSearchPooledConnectionFactory" />
<bean id="adDnResolver4" class="org.ldaptive.auth.PooledSearchDnResolver"
p:baseDn="%{idp.authn.LDAP.baseDN4}"
p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"
p:userFilter="%{idp.authn.LDAP.userFilter}"
p:connectionFactory-ref="adBindSearchPooledConnectionFactory" />
<!-- Define Directory1 Search-pool -->
<bean id="adBindSearchPooledConnectionFactory" class="org.ldaptive.pool.PooledConnectionFactory"
p:connectionPool-ref="adBindSearchConnectionPool" />
<bean id="adBindSearchConnectionPool" class="org.ldaptive.pool.BlockingConnectionPool"
parent="adConnectionPool"
p:connectionFactory-ref="adBindSearchConnectionFactory"
p:name="adSearch-pool" />
<bean id="adBindSearchConnectionFactory" class="org.ldaptive.DefaultConnectionFactory"
p:connectionConfig-ref="adBindSearchConnectionConfig" />
<bean id="adBindSearchConnectionConfig"
parent="adConnectionConfig"
p:connectionInitializer-ref="adBindConnectionInitializer" />
<bean id="adBindConnectionInitializer" class="org.ldaptive.BindConnectionInitializer"
p:bindDn="%{idp.authn.LDAP.bindDN}">
<property name="bindCredential">
<bean class="org.ldaptive.Credential">
<constructor-arg value="%{idp.authn.LDAP.bindDNCredential}" />
</bean>
</property>
</bean>
<util:map id="adAuthHandlers">
<entry key="directory_filter1" value-ref="adAuthHandler1" />
<entry key="directory_filter2" value-ref="adAuthHandler1" />
<entry key="directory_filter3" value-ref="adAuthHandler1" />
<entry key="directory_filter4" value-ref="adAuthHandler1" />
</util:map>
<!-- authentication handler for Directory DN resolver -->
<bean id="adAuthHandler1" class="org.ldaptive.auth.PooledBindAuthenticationHandler"
p:connectionFactory-ref="adBindPooledConnectionFactory" />
<bean id="adBindPooledConnectionFactory" class="org.ldaptive.pool.PooledConnectionFactory"
p:connectionPool-ref="adBindConnectionPool" />
<bean id="adBindConnectionPool" class="org.ldaptive.pool.BlockingConnectionPool"
parent="adConnectionPool"
p:connectionFactory-ref="adBindConnectionFactory"
p:name="adBind-pool" />
<bean id="adBindConnectionFactory" class="org.ldaptive.DefaultConnectionFactory"
p:connectionConfig-ref="adBindConnectionConfig" />
<bean id="adBindConnectionConfig"
parent="adConnectionConfig" />
Now we have to add the additional baseDN attributes that we defined and assign the other values in ldap.properties.
# LDAP authentication configuration, see authn/ldap-authn-config.xml
# Note, this doesn't apply to the use of JAAS
## Authenticator strategy, either anonSearchAuthenticator,
bindSearchAuthenticator, directAuthenticator, adAuthenticator
idp.authn.LDAP.authenticator = adAggregateAuthenticator
## Connection properties ##
idp.authn.LDAP.ldapURL = ldaps://ad1.skool.edu:636 ldaps://ad2.skool.edu:636
idp.authn.LDAP.useStartTLS = false
idp.authn.LDAP.useSSL = true
idp.authn.LDAP.connectTimeout = 3000
## SSL configuration, either jvmTrust, certificateTrust, or keyStoreTrust
idp.authn.LDAP.sslConfig = certificateTrust
## If using certificateTrust above, set to the trusted certificate's path
idp.authn.LDAP.trustCertificates = %{idp.home}/credentials/ldapserver.crt
## If using keyStoreTrust above, set to the truststore path
idp.authn.LDAP.trustStore = %{idp.home}/credentials/ldapserver.truststore
## Return attributes during authentication
## NOTE: there is a separate property used for attribute resolution
idp.authn.LDAP.returnAttributes = passwordExpirationTime,loginGraceRemaining
## DN resolution properties ##
# Search DN resolution, used by anonSearchAuthenticator,bindSearchAuthenticator
# for AD: CN=Users,DC=example,DC=org
#
idp.authn.LDAP.baseDN1 = OU=folder1,DC=skool,DC=edu
idp.authn.LDAP.baseDN2 = OU=subfolder1,OU=folder2,DC=skool,DC=edu
idp.authn.LDAP.baseDN3 = OU=folder3,DC=skool,DC=edu
idp.authn.LDAP.baseDN4 = OU=folder4,DC=skool,DC=edu
idp.authn.LDAP.subtreeSearch = false
#idp.authn.LDAP.userFilter = (uid={user})
idp.authn.LDAP.userFilter = (mail={user})
# bind search configuration
# for AD: idp.authn.LDAP.bindDN=adminuser@domain.com
idp.authn.LDAP.bindDN = CN=ADadmin,ou=managers,dc=skool,dc=edu
idp.authn.LDAP.bindDNCredential = secretsquirrel66!!!
# Format DN resolution, used by directAuthenticator, adAuthenticator
# for AD use idp.authn.LDAP.dnFormat=%s@domain.com
idp.authn.LDAP.dnFormat = uid=%s,ou=people,dc=example,dc=org
# LDAP attribute configuration, see attribute-resolver.xml
# Note, this likely won't apply to the use of legacy V2 resolver configurations
idp.attribute.resolver.LDAP.ldapURL = %{idp.authn.LDAP.ldapURL}
idp.attribute.resolver.LDAP.baseDN1 = %{idp.authn.LDAP.baseDN1:undefined}
idp.attribute.resolver.LDAP.baseDN2 = %{idp.authn.LDAP.baseDN2:undefined}
idp.attribute.resolver.LDAP.baseDN3 = %{idp.authn.LDAP.baseDN3:undefined}
idp.attribute.resolver.LDAP.baseDN4 = %{idp.authn.LDAP.baseDN4:undefined}
idp.attribute.resolver.LDAP.bindDN = %{idp.authn.LDAP.bindDN:undefined}
idp.attribute.resolver.LDAP.bindDNCredential = %{idp.authn.LDAP.bindDNCredential:undefined}
idp.attribute.resolver.LDAP.useStartTLS = %{idp.authn.LDAP.useStartTLS:true}
idp.attribute.resolver.LDAP.trustCertificates = %{idp.authn.LDAP.trustCertificates:undefined}
#idp.attribute.resolver.LDAP.searchFilter = (uid=$resolutionContext.principal)
idp.attribute.resolver.LDAP.searchFilter = (mail=$resolutionContext.principal)
idp.attribute.resolver.LDAP.returnAttributes = givenname,mail,samaccountname,sn
You should be able to login to test sites with your additional OU's now, but if your not seeing attributes released its because if you use the example attribute-resolver-ldap.xml for your attribute-resolver.xml file then there's only 1 DataConnector defined by default, and you have 4 (or more) DataConnectors. We'll replace the existing DataConnector with multiple DataConnectors in a failover
<resolver:DataConnector id="myLDAP" xsi:type="dc:LDAPDirectory"
ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}"
baseDN="%{idp.attribute.resolver.LDAP.baseDN1}"
principal="%{idp.attribute.resolver.LDAP.bindDN}"
principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}"
noResultIsError="True"
useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS::true}">
<resolver:FailoverDataConnector ref="myLDAP2" />
<dc:FilterTemplate>
<![CDATA[
%{idp.attribute.resolver.LDAP.searchFilter}
]]>
</dc:FilterTemplate>
<dc:ReturnAttributes>%{idp.attribute.resolver.LDAP.returnAttributes}</dc:ReturnAttributes>
<dc:LDAPProperty name="java.naming.referral" value="follow"/>
<dc:StartTLSTrustCredential id="LDAPtoIdPCredential" xsi:type="sec:X509ResourceBacked">
<sec:Certificate>%{idp.attribute.resolver.LDAP.trustCertificates}</sec:Certificate>
</dc:StartTLSTrustCredential>
</resolver:DataConnector>
<resolver:DataConnector id="myLDAP2" xsi:type="dc:LDAPDirectory"
ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}"
baseDN="%{idp.attribute.resolver.LDAP.baseDN2}"
principal="%{idp.attribute.resolver.LDAP.bindDN}"
principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}"
noResultIsError="True"
useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS::true}">
<resolver:FailoverDataConnector ref="myLDAP3" />
<dc:FilterTemplate>
<![CDATA[
%{idp.attribute.resolver.LDAP.searchFilter}
]]>
</dc:FilterTemplate>
<dc:ReturnAttributes>%{idp.attribute.resolver.LDAP.returnAttributes}</dc:ReturnAttributes>
<dc:LDAPProperty name="java.naming.referral" value="follow"/>
<dc:StartTLSTrustCredential id="LDAPtoIdPCredential" xsi:type="sec:X509ResourceBacked">
<sec:Certificate>%{idp.attribute.resolver.LDAP.trustCertificates}</sec:Certificate>
</dc:StartTLSTrustCredential>
</resolver:DataConnector>
<resolver:DataConnector id="myLDAP3" xsi:type="dc:LDAPDirectory"
ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}"
baseDN="%{idp.attribute.resolver.LDAP.baseDN3}"
principal="%{idp.attribute.resolver.LDAP.bindDN}"
principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}"
noResultIsError="True"
useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS::true}">
<resolver:FailoverDataConnector ref="myLDAP4" />
<dc:FilterTemplate>
<![CDATA[
%{idp.attribute.resolver.LDAP.searchFilter}
]]>
</dc:FilterTemplate>
<dc:ReturnAttributes>%{idp.attribute.resolver.LDAP.returnAttributes}</dc:ReturnAttributes>
<dc:LDAPProperty name="java.naming.referral" value="follow"/>
<dc:StartTLSTrustCredential id="LDAPtoIdPCredential" xsi:type="sec:X509ResourceBacked">
<sec:Certificate>%{idp.attribute.resolver.LDAP.trustCertificates}</sec:Certificate>
</dc:StartTLSTrustCredential>
</resolver:DataConnector>
<resolver:DataConnector id="myLDAP4" xsi:type="dc:LDAPDirectory"
ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}"
baseDN="%{idp.attribute.resolver.LDAP.baseDN4}"
principal="%{idp.attribute.resolver.LDAP.bindDN}"
principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}"
noResultIsError="True"
useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS::true}">
<dc:FilterTemplate>
<![CDATA[
%{idp.attribute.resolver.LDAP.searchFilter}
]]>
</dc:FilterTemplate>
<dc:ReturnAttributes>%{idp.attribute.resolver.LDAP.returnAttributes}</dc:ReturnAttributes>
<dc:LDAPProperty name="java.naming.referral" value="follow"/>
<dc:StartTLSTrustCredential id="LDAPtoIdPCredential" xsi:type="sec:X509ResourceBacked">
<sec:Certificate>%{idp.attribute.resolver.LDAP.trustCertificates}</sec:Certificate>
</dc:StartTLSTrustCredential>
</resolver:DataConnector>
Related articles
Filter by label
There are no items with the selected labels at this time.