The Shibboleth IdP V3 software has reached its End of Life and is no longer supported. This documentation is available for historical purposes only. See the IDP4 wiki space for current documentation on the supported version.
Authenticating against multiple OU's
- daniel.mcdonald@umb.edu
- Scott Cantor
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
ldap-authn-config.xml Expand source<!-- 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.
Attribute Matching
Note that we match on the attribute "mail" because of our structure, but I think most AD users would want to match on sAMAccountName if you want to match on just "username". If you'd rather match on "username@domain.com" then use userPrincipalName. Also we have idp.authn.LDAP.subtreeSearch set to false because we have OU's we dont want searched, but most people enable this.
ldap.properties Expand source# 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
attribute-resolver.xml Expand source<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.