<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=utf-8">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    I didnt see alot of documentation for authenticating against
    multiple OU's in AD in shibboleth IdP v3.2.1 so I thought i'd share
    my setup in case anyone else is trying to do the same thing. In our
    AD these are all top level OU's and we have some OU's that we dont
    want searched so we cant use subtreeSearch. This is based on the
    example from the shibboleth LDAPAuthnConfiguration doc titled
    "Complete example with DN resolvers and authentication handlers for
    bindSearch" which is for 2 AD servers with 2 directories each. While
    this worked for us, we had 1 AD server with 4 directories so we
    changed it a bit to fit us better. After making the changes to
    ldap-authn-config.xml and ldap.properties we could login OK, but
    attributes werent being released. I realized it was because
    attribute-resolver.xml by default only had 1 dataconnector to
    release attributes for 1 directory so we had to modify that to add
    our other 3 dataconnectors as failovers. <br>
    <br>
    Active Directory doesnt support extensible match rules else we could
    of just done <span class="s1">idp.authn.LDAP.userFilter=</span><span
      style="color: rgb(34,34,34);">(&(|(ou:dn:=people)(ou:dn:=</span><span
      style="color: rgb(34,34,34);">guests))(uid={user})) and saved
      ourselves alot of work.  :)</span><br>
    <br>
    I actually dont know java beans (or really shibboleth for that
    matter), so if someone sees a more elegant way to do this plz let me
    know. <br>
     <br>
    Added this config for adAuthenticator at the end of
    ldap-authn-config.xml, left the existing defined configs untouched:<br>
    <br>
        <!-- Active Directory Configuration for 1 server with 4 OU's
    --><br>
        <bean id="adAuthenticator"
    class="org.ldaptive.auth.Authenticator"
    p:authenticationResponseHandlers-ref="authenticationResponseHandler"<br>
           
p:resolveEntryOnFailure="%{idp.authn.LDAP.resolveEntryOnFailure:false}"><br>
            <constructor-arg index="0" ref="formatDnResolver" /><br>
            <constructor-arg index="1" ref="authHandler" /><br>
        </bean><br>
        <bean id="authenticationResponseHandler"
class="org.ldaptive.auth.ext.ActiveDirectoryAuthenticationResponseHandler"
    /><br>
    <br>
    <!-- Define Directory1 connection pool --><br>
        <bean id="adConnectionPool"
    class="org.ldaptive.pool.BlockingConnectionPool" abstract="true"<br>
            p:blockWaitTime="%{idp.pool.LDAP.blockWaitTime:3000}"<br>
            p:poolConfig-ref="adPoolConfig"<br>
            p:pruneStrategy-ref="adPruneStrategy"<br>
            p:validator-ref="adSearchValidator"<br>
           
    p:failFastInitialize="%{idp.pool.LDAP.failFastInitialize:false}"
    /><br>
        <bean id="adPoolConfig" class="org.ldaptive.pool.PoolConfig"<br>
            p:minPoolSize="%{idp.pool.LDAP.minSize:3}"<br>
            p:maxPoolSize="%{idp.pool.LDAP.maxSize:10}"<br>
           
    p:validateOnCheckOut="%{idp.pool.LDAP.validateOnCheckout:false}"<br>
           
    p:validatePeriodically="%{idp.pool.LDAP.validatePeriodically:true}"<br>
            p:validatePeriod="%{idp.pool.LDAP.validatePeriod:300}" /><br>
        <bean id="adPruneStrategy"
    class="org.ldaptive.pool.IdlePruneStrategy"<br>
            p:prunePeriod="%{idp.pool.LDAP.prunePeriod:300}"<br>
            p:idleTime="%{idp.pool.LDAP.idleTime:600}" /><br>
        <bean id="adSearchValidator"
    class="org.ldaptive.pool.SearchValidator" /><br>
    <!-- Directory1 connection pool settings --><br>
        <bean id="adConnectionConfig"
    class="org.ldaptive.ConnectionConfig" abstract="true"<br>
            p:ldapUrl="%{idp.authn.LDAP.ldapURL}"<br>
            p:useStartTLS="%{idp.authn.LDAP.useStartTLS:true}"<br>
            p:useSSL="%{idp.authn.LDAP.useSSL:false}"<br>
            p:connectTimeout="%{idp.authn.LDAP.connectTimeout:3000}"<br>
            p:sslConfig-ref="adSslConfig" /><br>
        <alias name="%{idp.authn.LDAP.sslConfig:certificateTrust}"
    alias="adSslConfig" /><br>
    <!-- ldap.properties "idp.authn.LDAP.authenticator =
    adAggregateAuthenticator" --><br>
        <bean id="adAggregateAuthenticator"
    class="org.ldaptive.auth.Authenticator"<br>
           
p:authenticationResponseHandlers-ref="adAuthenticationResponseHandler"><br>
            <constructor-arg index="0" ref="adAggregateDnResolver"
    /><br>
            <constructor-arg index="1" ref="adAggregateAuthHandler"
    /><br>
        </bean><br>
        <bean id="adAuthenticationResponseHandler"
class="org.ldaptive.auth.ext.ActiveDirectoryAuthenticationResponseHandler"
    /><br>
        <bean id="adAggregateDnResolver"
    class="org.ldaptive.auth.AggregateDnResolver"><br>
            <constructor-arg index="0" ref="adDnResolvers" /><br>
        </bean><br>
        <bean id="adAggregateAuthHandler"
    class="org.ldaptive.auth.AggregateDnResolver$AuthenticationHandler"<br>
            p:authenticationHandlers-ref="adAuthHandlers" /><br>
        <util:map id="adDnResolvers"><br>
            <entry key="directory_filter1" value-ref="adDnResolver1"
    /><br>
            <entry key="directory_filter2" value-ref="adDnResolver2"
    /><br>
            <entry key="directory_filter3" value-ref="adDnResolver3"
    /><br>
            <entry key="directory_filter4" value-ref="adDnResolver4"
    /><br>
        </util:map><br>
    <!-- Define four DN resolvers that bind search against the
    Directory --><br>
        <bean id="adDnResolver1"
    class="org.ldaptive.auth.PooledSearchDnResolver"<br>
            p:baseDn="%{idp.authn.LDAP.baseDN1}"<br>
            p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"<br>
            p:userFilter="%{idp.authn.LDAP.userFilter}"<br>
           
    p:connectionFactory-ref="adBindSearchPooledConnectionFactory" /><br>
        <bean id="adDnResolver2"
    class="org.ldaptive.auth.PooledSearchDnResolver"<br>
            p:baseDn="%{idp.authn.LDAP.baseDN2}"<br>
            p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"<br>
            p:userFilter="%{idp.authn.LDAP.userFilter}"<br>
           
    p:connectionFactory-ref="adBindSearchPooledConnectionFactory" /><br>
        <bean id="adDnResolver3"
    class="org.ldaptive.auth.PooledSearchDnResolver"<br>
            p:baseDn="%{idp.authn.LDAP.baseDN3}"<br>
            p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"<br>
            p:userFilter="%{idp.authn.LDAP.userFilter}"<br>
           
    p:connectionFactory-ref="adBindSearchPooledConnectionFactory" /><br>
        <bean id="adDnResolver4"
    class="org.ldaptive.auth.PooledSearchDnResolver"<br>
            p:baseDn="%{idp.authn.LDAP.baseDN4}"<br>
            p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"<br>
            p:userFilter="%{idp.authn.LDAP.userFilter}"<br>
           
    p:connectionFactory-ref="adBindSearchPooledConnectionFactory" /><br>
    <!-- Define Directory1 Search-pool --><br>
        <bean id="adBindSearchPooledConnectionFactory"
    class="org.ldaptive.pool.PooledConnectionFactory"<br>
            p:connectionPool-ref="adBindSearchConnectionPool" /><br>
        <bean id="adBindSearchConnectionPool"
    class="org.ldaptive.pool.BlockingConnectionPool"<br>
            parent="adConnectionPool"<br>
            p:connectionFactory-ref="adBindSearchConnectionFactory"<br>
            p:name="adSearch-pool" /><br>
        <bean id="adBindSearchConnectionFactory"
    class="org.ldaptive.DefaultConnectionFactory"<br>
            p:connectionConfig-ref="adBindSearchConnectionConfig" /><br>
        <bean id="adBindSearchConnectionConfig"<br>
            parent="adConnectionConfig"<br>
            p:connectionInitializer-ref="adBindConnectionInitializer"
    /><br>
        <bean id="adBindConnectionInitializer"
    class="org.ldaptive.BindConnectionInitializer"<br>
            p:bindDn="%{idp.authn.LDAP.bindDN}"><br>
            <property name="bindCredential"><br>
                <bean class="org.ldaptive.Credential"><br>
                    <constructor-arg
    value="%{idp.authn.LDAP.bindDNCredential}" /><br>
                </bean><br>
            </property><br>
        </bean><br>
        <util:map id="adAuthHandlers"><br>
            <entry key="directory_filter1" value-ref="adAuthHandler1"
    /><br>
            <entry key="directory_filter2" value-ref="adAuthHandler1"
    /><br>
            <entry key="directory_filter3" value-ref="adAuthHandler1"
    /><br>
            <entry key="directory_filter4" value-ref="adAuthHandler1"
    /><br>
        </util:map><br>
    <!-- authentication handler for Directory DN resolver --><br>
        <bean id="adAuthHandler1"
    class="org.ldaptive.auth.PooledBindAuthenticationHandler"<br>
            p:connectionFactory-ref="adBindPooledConnectionFactory"
    /><br>
        <bean id="adBindPooledConnectionFactory"
    class="org.ldaptive.pool.PooledConnectionFactory"<br>
            p:connectionPool-ref="adBindConnectionPool" /><br>
        <bean id="adBindConnectionPool"
    class="org.ldaptive.pool.BlockingConnectionPool"<br>
            parent="adConnectionPool"<br>
            p:connectionFactory-ref="adBindConnectionFactory"<br>
            p:name="adBind-pool" /><br>
        <bean id="adBindConnectionFactory"
    class="org.ldaptive.DefaultConnectionFactory"<br>
            p:connectionConfig-ref="adBindConnectionConfig" /><br>
        <bean id="adBindConnectionConfig"<br>
            parent="adConnectionConfig" /><br>
    <br>
    ldap.properties:<br>
    <br>
    # LDAP authentication configuration, see authn/ldap-authn-config.xml<br>
    # Note, this doesn't apply to the use of JAAS<br>
    <br>
    ## Authenticator strategy, either anonSearchAuthenticator,
    bindSearchAuthenticator, directAuthenticator, adAuthenticator<br>
    idp.authn.LDAP.authenticator                   =
    adAggregateAuthenticator<br>
    <br>
    ## Connection properties ##<br>
    idp.authn.LDAP.ldapURL                         =
    <a class="moz-txt-link-freetext" href="ldaps://ad1.skool.edu:636">ldaps://ad1.skool.edu:636</a> <a class="moz-txt-link-freetext" href="ldaps://ad2.skool.edu:636">ldaps://ad2.skool.edu:636</a><br>
    idp.authn.LDAP.useStartTLS                     = false<br>
    idp.authn.LDAP.useSSL                          = true<br>
    idp.authn.LDAP.connectTimeout                  = 3000<br>
    <br>
    ## SSL configuration, either jvmTrust, certificateTrust, or
    keyStoreTrust<br>
    idp.authn.LDAP.sslConfig                       = certificateTrust<br>
    ## If using certificateTrust above, set to the trusted certificate's
    path<br>
    idp.authn.LDAP.trustCertificates                =
    %{idp.home}/credentials/ldap-server.crt<br>
    ## If using keyStoreTrust above, set to the truststore path<br>
    idp.authn.LDAP.trustStore                       =
    %{idp.home}/credentials/ldap-server.truststore<br>
    <br>
    ## Return attributes during authentication<br>
    ## NOTE: there is a separate property used for attribute resolution<br>
    idp.authn.LDAP.returnAttributes                 =
    passwordExpirationTime,loginGraceRemaining<br>
    <br>
    ## DN resolution properties ##<br>
    <br>
    # Search DN resolution, used by anonSearchAuthenticator,
    bindSearchAuthenticator<br>
    # for AD: CN=Users,DC=example,DC=org<br>
    #<br>
    idp.authn.LDAP.baseDN1                          =
    OU=folder1,DC=skool,DC=edu<br>
    idp.authn.LDAP.baseDN2                          =
    OU=subfolder1,OU=folder2,DC=skool,DC=edu<br>
    idp.authn.LDAP.baseDN3                          =
    OU=folder3,DC=skool,DC=edu<br>
    idp.authn.LDAP.baseDN4                          =
    OU=folder4,DC=skool,DC=edu<br>
    idp.authn.LDAP.subtreeSearch                    = false<br>
    #idp.authn.LDAP.userFilter                       = (uid={user})<br>
    idp.authn.LDAP.userFilter                      = (mail={user})<br>
    # bind search configuration <br>
    # for AD: <a class="moz-txt-link-abbreviated" href="mailto:idp.authn.LDAP.bindDN=adminuser@domain.com">idp.authn.LDAP.bindDN=adminuser@domain.com</a><br>
    idp.authn.LDAP.bindDN                           =
    CN=ADadmin,ou=managers,dc=skool,dc=edu<br>
    idp.authn.LDAP.bindDNCredential                 =
    secretsquirrel66!!!<br>
        <br>
    # Format DN resolution, used by directAuthenticator, adAuthenticator<br>
    # for AD use <a class="moz-txt-link-abbreviated" href="mailto:idp.authn.LDAP.dnFormat=%s@domain.com">idp.authn.LDAP.dnFormat=%s@domain.com</a> <br>
    idp.authn.LDAP.dnFormat                         =
    uid=%s,ou=people,dc=example,dc=org<br>
        <br>
    # LDAP attribute configuration, see attribute-resolver.xml<br>
    # Note, this likely won't apply to the use of legacy V2 resolver
    configurations<br>
    idp.attribute.resolver.LDAP.ldapURL             =
    %{idp.authn.LDAP.ldapURL}<br>
    idp.attribute.resolver.LDAP.baseDN1              =
    %{idp.authn.LDAP.baseDN1:undefined}<br>
    idp.attribute.resolver.LDAP.baseDN2              =
    %{idp.authn.LDAP.baseDN2:undefined}<br>
    idp.attribute.resolver.LDAP.baseDN3              =
    %{idp.authn.LDAP.baseDN3:undefined}<br>
    idp.attribute.resolver.LDAP.baseDN4              =
    %{idp.authn.LDAP.baseDN4:undefined}<br>
    idp.attribute.resolver.LDAP.bindDN              =
    %{idp.authn.LDAP.bindDN:undefined}<br>
    idp.attribute.resolver.LDAP.bindDNCredential    =
    %{idp.authn.LDAP.bindDNCredential:undefined}<br>
    idp.attribute.resolver.LDAP.useStartTLS         =
    %{idp.authn.LDAP.useStartTLS:true}<br>
    idp.attribute.resolver.LDAP.trustCertificates   =
    %{idp.authn.LDAP.trustCertificates:undefined}<br>
    #idp.attribute.resolver.LDAP.searchFilter        =
    (uid=$resolutionContext.principal)<br>
    idp.attribute.resolver.LDAP.searchFilter        =
    (mail=$requestContext.principalName)<br>
    idp.attribute.resolver.LDAP.returnAttributes    =
    givenname,mail,miservice,samaccountname,sn<br>
    <br>
    The dataconnectors from attribute-resolver.xml. Basically if the
    search doesnt match in an OU it fails to the next.<br>
    <br>
    <resolver:DataConnector id="myLDAP" xsi:type="dc:LDAPDirectory"<br>
            ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}"<br>
            baseDN="%{idp.attribute.resolver.LDAP.baseDN1}" <br>
            principal="%{idp.attribute.resolver.LDAP.bindDN}"<br>
           
    principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}"<br>
            noResultIsError="True"<br>
           
    useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS::true}"><br>
    <br>
            <resolver:FailoverDataConnector ref="myLDAP2" /><br>
    <br>
            <dc:FilterTemplate><br>
                <![CDATA[<br>
                    %{idp.attribute.resolver.LDAP.searchFilter}<br>
                ]]><br>
            </dc:FilterTemplate><br>
           
<dc:ReturnAttributes>%{idp.attribute.resolver.LDAP.returnAttributes}</dc:ReturnAttributes><br>
            <dc:LDAPProperty name="java.naming.referral"
    value="follow"/><br>
            <dc:StartTLSTrustCredential id="LDAPtoIdPCredential"
    xsi:type="sec:X509ResourceBacked"><br>
               
<sec:Certificate>%{idp.attribute.resolver.LDAP.trustCertificates}</sec:Certificate><br>
            </dc:StartTLSTrustCredential><br>
    <br>
        </resolver:DataConnector><br>
    <br>
        <resolver:DataConnector id="myLDAP2"
    xsi:type="dc:LDAPDirectory"<br>
            ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}"<br>
            baseDN="%{idp.attribute.resolver.LDAP.baseDN2}" <br>
            principal="%{idp.attribute.resolver.LDAP.bindDN}"<br>
           
    principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}"<br>
            noResultIsError="True"<br>
           
    useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS::true}"><br>
    <br>
            <resolver:FailoverDataConnector ref="myLDAP3" /><br>
            <dc:FilterTemplate><br>
                <![CDATA[<br>
                    %{idp.attribute.resolver.LDAP.searchFilter}<br>
                ]]><br>
            </dc:FilterTemplate><br>
           
<dc:ReturnAttributes>%{idp.attribute.resolver.LDAP.returnAttributes}</dc:ReturnAttributes><br>
            <dc:LDAPProperty name="java.naming.referral"
    value="follow"/><br>
            <dc:StartTLSTrustCredential id="LDAPtoIdPCredential"
    xsi:type="sec:X509ResourceBacked"><br>
               
<sec:Certificate>%{idp.attribute.resolver.LDAP.trustCertificates}</sec:Certificate><br>
            </dc:StartTLSTrustCredential><br>
    <br>
        </resolver:DataConnector><br>
    <br>
    And so on for myLDAP3 & 4. On The last entry leave out the
    <resolver:FailoverDataConnector><br>
    <br>
  </body>
</html>