/
LDAPAuthnConfiguration

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.

LDAPAuthnConfiguration

Current File(s): conf/authn/ldap-authn-config.xml

Format: Native Spring

V2 Legacy File(s): conf/handler.xml, conf/login.config

Overview

This back-end for the password authentication login flow uses native LDAP libraries for password-based authentication instead of using a JAAS module. The primary advantages are slightly better performance and more control over the process, such as the ability to extract detailed account status information from the directory during a login.

General Configuration

Configuring LDAP as a back-end requires that the right import is active in authn/password-authn-config.xml:

Import in authn/password-authn-config.xml
<import resource="ldap-authn-config.xml" />

The other imports must be commented or removed.

A large number of beans are defined in authn/ldap-authn-config.xml to configure this back-end, but in most cases the properties in ldap.properties can do most of the work needed. The beans can be used for very advanced cases where a higher degree of control is required.

A bean alias is also defined that instantiates the LDAP back-end action as the "ValidateUsernamePassword" step of the web flow. This must not be changed.

Basic Configuration

Authenticator Configuration

The idp.authn.LDAP.authenticator property controls the workflow for how authentication occurs against the LDAP directory:

anonSearchAuthenticator

Performs an anonymous search for the user's DN

bindSearchAuthenticator

Binds as a configured DN then searches for the user's DN

directAuthenticator

User DNs are of a known format. i.e. CN=user_name,ou=accounts,dc=domain,dc=edu. No DN search is performed.

adAuthenticator

Configuration that leverages the AD specific @domain.com format. No DN search is performed since AD supports binding directly with that user name.

Depending on the choice above, various other properties must be set (see the reference section below).

Connection Configuration

Use the following properties to configure basic connection information for the LDAP directory:

  • idp.authn.LDAP.ldapURL
  • idp.authn.LDAP.useStartTLS
  • idp.authn.LDAP.useSSL
  • idp.authn.LDAP.connectTimeout

A connection pool is used, and there are several properties used to configure pool behavior (see the reference below).

SSL Configuration

If StartTLS or SSL are used, a source of trust anchors must be configured to control certificate validation, using the idp.authn.LDAP.sslConfig property:

certificateTrust

Uses the idp.authn.LDAP.trustCertificates property to load a resource containing the trust anchors (such as a file of PEM-format certificates)

keyStoreTrust

Uses the idp.authn.LDAP.trustStore property to load a keystore containing the trust anchors

jvmTrust

Uses the default JVM trust anchors (the JVM-wide "cacerts" file)

Advanced Configuration

Use authn/ldap-authn-config.xml to perform advanced configuration. The beans in this file correspond to properties of the Ldaptive authentication interface (see http://www.ldaptive.org/docs/guide/authentication). If you want to completely alter the LDAP objects used, you may want to consider copying the file to create your own version, and modify the beans used.

Reference

Beans

Some of the most important beans defined in authn/ldap-authn-config.xml follow.

Many other beans are defined in the file subordinate to the beans below. You are free to modify them as you see fit. Only the first two beans below are actually used by the login flow; the rest are injected into the shibboleth.authn.LDAP.authenticator bean to make up its content.

Bean IDTypeDefaultFunction
shibboleth.authn.LDAP.authenticatororg.ldaptive.auth.Authenticator
Must be set to a bean of the appropriate type to configure the LDAP authentication library, normally a property-controlled alias for one of: anonSearchAuthenticator, bindSearchAuthenticator, directAuthenticator, or adAuthenticator
shibboleth.authn.LDAP.returnAttributesjava.util.Collection<String>
The collection of attribute names to return in the LDAP operation, normally set via property
shibboleth.X509ResourceCredentialConfigResource path
A parent bean for supplying Ldaptive CredentialConfig instances using Spring resources containing X.509 trust anchors
shibboleth.KeystoreResourceCredentialConfigResource path
A parent bean for supplying Ldaptive CredentialConfig instances using Spring resources containing a Java keystore
sslConfigorg.ldaptive.ssl.SslConfig
Must be set to a bean of the appropriate type to configure the TLS trust source, normally a property-controlled alias for one of jvmTrust, certificateTrust, keystoreTrust

Properties

A number of properties are found in ldap.properties to configure LDAP authentication. Most of the time, this is sufficient to deal with most configurations without having to delve into modifying any beans.

PropertyTypeDefaultFunction
idp.authn.LDAP.authenticatorEnumerationanonSearchAuthenticatorControls the workflow for how authentication occurs against the LDAP, one of: anonSearchAuthenticator, bindSearchAuthenticator, directAuthenticator, adAuthenticator
idp.authn.LDAP.ldapURLLDAP URI
Connection URI for LDAP directory
idp.authn.LDAP.useStartTLSBooleantrueWhether StartTLS should be used after connecting with LDAP alone
idp.authn.LDAP.useSSLBooleanfalseWhether SSL should be used directly
idp.authn.LDAP.connectTimeoutInteger3000 (PT3S) 3.3Connection timeout in milliseconds
idp.authn.LDAP.responseTimeout 3.3DurationPT3S
idp.authn.LDAP.sslConfigEnumerationcertificateTrustHow to establish trust in the server's TLS certificate, one of: jvmTrust, certificateTrust, or keyStoreTrust
idp.authn.LDAP.trustCertificatesResource path
A resource to load trust anchors from, usually a local file in %{idp.home}/credentials
idp.authn.LDAP.trustStoreResource path
A resource to load a Java keystore containing trust anchors, usually a local file in %{idp.home}/credentials
idp.authn.LDAP.returnAttributesComma-sep'd Strings
List of attributes to request during authentication
idp.authn.LDAP.baseDNString
Base DN to search against, used by anonSearchAuthenticator, bindSearchAuthenticator
idp.authn.LDAP.subtreeSearchBooleanfalseWhether to search recursively, used by anonSearchAuthenticator, bindSearchAuthenticator
idp.authn.LDAP.userFilterString
LDAP search filter, used by anonSearchAuthenticator, bindSearchAuthenticator
idp.authn.LDAP.bindDNString
DN to bind with during search, used by bindSearchAuthenticator
idp.authn.LDAP.bindDNCredentialString
Password to bind with during search, used by bindSearchAuthenticator
idp.authn.LDAP.dnFormatString
A formatting string to generate the user DNs to authenticate, used by directAuthenticator, adAuthenticator
idp.pool.LDAP.minSizeInteger3Minimum LDAP connection pool size
idp.pool.LDAP.maxSizeInteger10Maximum LDAP connection pool size
idp.pool.LDAP.validateOnCheckoutBooleanfalseWhether to validate connections when checking them out of the pool
idp.pool.LDAP.validatePeriodicallyBooleantrueWhether to validate connections in the background
idp.pool.LDAP.validatePeriodInteger300 (PT5M) 3.3Interval in seconds between validation, if idp.pool.LDAP.validatePeriodically is true
idp.pool.LDAP.prunePeriodInteger300 (PT5M) 3.3Interval in seconds between looking for idle connections to reduce the pool back to its minimum size
idp.pool.LDAP.idleTimeInteger600 (PT10M) 3.3Time in seconds that connections must be idle to be eligible for pruning
idp.pool.LDAP.blockWaitTimeInteger3000 (PT3S) 3.3Time in milliseconds to wait for a free connection in the pool
idp.pool.LDAP.failFastInitializeBooleanfalseWhether to fail initialization of the components using the LDAP connection pool if the pool can't be established, or treat as a connection failure later

Attribute Retrieval

LDAP attributes are returned as part of the authentication process and exposed in the LDAPResponseContext.

PropertyValueResult
idp.authn.LDAP.returnAttributesuid,

eduPersonAffiliation

Returns the uid and

eduPersonAffiliation attributes.

idp.authn.LDAP.returnAttributes*Returns all user attributes on the entry.
idp.authn.LDAP.returnAttributes*,+Returns all user and operational attributes on the entry.
idp.authn.LDAP.returnAttributes1.1No attribute returned. No search performed.


By default, attributes will be searched for using the same connection the user authenticated on. Therefore the user must have read on any attributes for those to be returned. If you need access to attributes that user does not have read access to, then you must configure a connection pool that is authorized to read. The following configuration demonstrates how to add a new connection pool for that purpose.

ldap-authn-config.xml
<!-- Modify the authenticator to use the entry resolver -->
<bean name="anonSearchAuthenticator" class="org.ldaptive.auth.Authenticator" p:entryResolver-ref="bindSearchEntryResolver">
...
 
<!-- Add an entry resolver to read attributes -->
<bean id="bindSearchEntryResolver" class="org.ldaptive.auth.PooledSearchEntryResolver" p:connectionFactory-ref="entryResolverPooledConnectionFactory" />
<bean id="entryResolverPooledConnectionFactory" class="org.ldaptive.pool.PooledConnectionFactory" p:connectionPool-ref="entryResolverConnectionPool" />
<bean id="entryResolverConnectionPool" class="org.ldaptive.pool.BlockingConnectionPool" parent="connectionPool" p:connectionFactory-ref="entryResolverConnectionFactory" p:name="entry-resolver-pool" />
<bean id="entryResolverConnectionFactory" class="org.ldaptive.DefaultConnectionFactory" p:connectionConfig-ref="entryResolverConnectionConfig" />
<bean id="entryResolverConnectionConfig" parent="connectionConfig" p:connectionInitializer-ref="entryResolverConnectionInitializer" />
<bean id="entryResolverConnectionInitializer" class="org.ldaptive.BindConnectionInitializer" p:bindDn="%{idp.authn.LDAP.entryResolver.bindDN}">
    <property name="bindCredential">
        <bean class="org.ldaptive.Credential">
            <constructor-arg value="%{idp.authn.LDAP.entryResolver.bindDNCredential}" />
        </bean>
    </property>
</bean>

Add the idp.authn.LDAP.entryResolver.bindDN and idp.authn.LDAP.entryResolver.bindDNCredential properties to conf/ldap.properties to complete the configuration.

Note: if you're using the bindSearchAuthenticator and those credentials can be reused for entry resolution, then this configuration can be shortened by wiring the bindPooledConnectionFactory to the entry resolver.

DN Resolution

Single Directory with multiple branches

Extensible Matching

If your directory supports extensible matching, this is easiest way to find users that are distributed over multiple branches.

PropertyValueResult

idp.authn.LDAP.userFilter

(&(|(ou:dn:=people)(ou:dn:=guests))(uid={user}))Returns the entry that matches uid on either the people or guests branch.

idp.authn.LDAP.baseDN

dc=example,dc=orgThe branch containing both ou=people and ou=guests.

idp.authn.LDAP.subtreeSearch

trueEnable subtree searching on the dc=example,dc=org branch.

Aggregate DN Resolver

This authenticator combines the results of multiple DN resolvers.

ldap-authn-config.xml
<bean name="aggregateAuthenticator" class="org.ldaptive.auth.Authenticator">
    <constructor-arg index="0" ref="aggregateDnResolver" />
    <constructor-arg index="1" ref="aggregateAuthHandler" />
</bean>
<bean id="aggregateDnResolver" class="org.ldaptive.auth.AggregateDnResolver">
    <constructor-arg index="0" ref="dnResolvers" />
</bean>
<bean id="aggregateAuthHandler" class="org.ldaptive.auth.AggregateDnResolver$AuthenticationHandler" p:authenticationHandlers-ref="authHandlers" />
<util:map id="dnResolvers">
    <entry key="filter1" value-ref="dnResolver1" />
    <entry key="filter2" value-ref="dnResolver2" />
</util:map>
<!-- Define two DN resolvers that use anonymous search against the same directory -->
<bean id="dnResolver1" class="org.ldaptive.auth.PooledSearchDnResolver" p:baseDn="%{idp.authn.LDAP.baseDN1}"
      p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}" p:userFilter="%{idp.authn.LDAP.userFilter1}"
      p:connectionFactory-ref="anonSearchPooledConnectionFactory" />
<bean id="dnResolver2" class="org.ldaptive.auth.PooledSearchDnResolver" p:baseDn="%{idp.authn.LDAP.baseDN2}"
      p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}" p:userFilter="%{idp.authn.LDAP.userFilter2}"
      p:connectionFactory-ref="anonSearchPooledConnectionFactory" />
<!-- Use the same authentication handler for both DN resolvers -->
<util:map id="authHandlers">
    <entry key="filter1" value-ref="authHandler" />
    <entry key="filter2" value-ref="authHandler" />
</util:map>

Add the idp.authn.LDAP.baseDN[12] and idp.authn.LDAP.userFilter[12] properties to conf/ldap.properties to complete the configuration. The key values used in dnResolvers and authHandlers can be anything, but must tie a single DN resolver to a single auth handler. By default an error will occur if more than (1) DN is resolved.

Multiple Directories

Aggregate DN Resolver

This authenticator combines the results of multiple DN resolvers that connect to multiple directories.

ldap-authn-config.xml
<bean name="aggregateAuthenticator" class="org.ldaptive.auth.Authenticator">
    <constructor-arg index="0" ref="aggregateDnResolver" />
    <constructor-arg index="1" ref="aggregateAuthHandler" />
</bean>
<bean id="aggregateDnResolver" class="org.ldaptive.auth.AggregateDnResolver">
    <constructor-arg index="0" ref="dnResolvers" />
</bean>
<bean id="aggregateAuthHandler" class="org.ldaptive.auth.AggregateDnResolver$AuthenticationHandler" p:authenticationHandlers-ref="authHandlers" />
<util:map id="dnResolvers">
    <entry key="directory1" value-ref="dnResolver1" />
    <entry key="directory2" value-ref="dnResolver2" />
</util:map>
<util:map id="authHandlers">
    <entry key="directory1" value-ref="authHandler1" />
    <entry key="directory2" value-ref="authHandler2" />
</util:map>
<!-- define DN resolvers and authentication handlers for each directory... -->
Complete example with DN resolvers and authentication handlers for bindSearch
<!-- Properties:
- idp.authn.LDAP.authenticator = aggregateAuthenticator
- idp.authn.LDAP.ldapURL1
- idp.authn.LDAP.ldapURL2
- idp.authn.LDAP.baseDN1
- idp.authn.LDAP.baseDN2
- idp.authn.LDAP.userFilter1
- idp.authn.LDAP.userFilter2
- idp.authn.LDAP.bindDN1
- idp.authn.LDAP.bindDN2
- idp.authn.LDAP.bindDNCredential1
- idp.authn.LDAP.bindDNCredential2
-->
<bean id="aggregateAuthenticator" class="org.ldaptive.auth.Authenticator"
      c:resolver-ref="aggregateDnResolver"
      c:handler-ref="aggregateAuthHandler" />

<!-- Aggregate DN resolution -->
<bean id="aggregateDnResolver" class="org.ldaptive.auth.AggregateDnResolver"
      c:resolvers-ref="dnResolvers"
      p:allowMultipleDns="true" />
<util:map id="dnResolvers">
    <entry key="directory1" value-ref="bindSearchDnResolver1" />
    <entry key="directory2" value-ref="bindSearchDnResolver2" />
</util:map>

<!-- DN resolver 1 -->
<bean id="bindSearchDnResolver1" class="org.ldaptive.auth.PooledSearchDnResolver"
      p:baseDn="#{'%{idp.authn.LDAP.baseDN1:undefined}'.trim()}"
      p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"
      p:userFilter="#{'%{idp.authn.LDAP.userFilter1:undefined}'.trim()}"
      p:connectionFactory-ref="bindSearchPooledConnectionFactory1" />
<bean id="bindSearchPooledConnectionFactory1" class="org.ldaptive.pool.PooledConnectionFactory"
      p:connectionPool-ref="bindSearchConnectionPool1" />
<bean id="bindSearchConnectionPool1" class="org.ldaptive.pool.BlockingConnectionPool" parent="connectionPool"
      p:connectionFactory-ref="bindSearchConnectionFactory1"
      p:name="search-pool1" />
<bean id="bindSearchConnectionFactory1" class="org.ldaptive.DefaultConnectionFactory"
      p:connectionConfig-ref="bindSearchConnectionConfig1" />
<bean id="bindSearchConnectionConfig1" parent="connectionConfig"
      p:connectionInitializer-ref="bindConnectionInitializer1"
      p:ldapUrl="%{idp.authn.LDAP.ldapURL1}" />
<bean id="bindConnectionInitializer1" class="org.ldaptive.BindConnectionInitializer"
      p:bindDn="#{'%{idp.authn.LDAP.bindDN1:undefined}'.trim()}">
    <property name="bindCredential">
    <bean class="org.ldaptive.Credential" c:password="%{idp.authn.LDAP.bindDNCredential1:undefined}" />
    </property>
</bean>
<!-- DN resolver 2 -->
<bean id="bindSearchDnResolver2" class="org.ldaptive.auth.PooledSearchDnResolver"
      p:baseDn="#{'%{idp.authn.LDAP.baseDN2:undefined}'.trim()}"
      p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"
      p:userFilter="#{'%{idp.authn.LDAP.userFilter2:undefined}'.trim()}"
      p:connectionFactory-ref="bindSearchPooledConnectionFactory2" />
<bean id="bindSearchPooledConnectionFactory2" class="org.ldaptive.pool.PooledConnectionFactory"
      p:connectionPool-ref="bindSearchConnectionPool2" />
<bean id="bindSearchConnectionPool2" class="org.ldaptive.pool.BlockingConnectionPool" parent="connectionPool"
      p:connectionFactory-ref="bindSearchConnectionFactory2"
      p:name="search-pool2" />
<bean id="bindSearchConnectionFactory2" class="org.ldaptive.DefaultConnectionFactory"
      p:connectionConfig-ref="bindSearchConnectionConfig2" />
<bean id="bindSearchConnectionConfig2" parent="connectionConfig"
      p:connectionInitializer-ref="bindConnectionInitializer2"
      p:ldapUrl="%{idp.authn.LDAP.ldapURL2}" />
<bean id="bindConnectionInitializer2" class="org.ldaptive.BindConnectionInitializer"
      p:bindDn="#{'%{idp.authn.LDAP.bindDN2:undefined}'.trim()}">
    <property name="bindCredential">
        <bean class="org.ldaptive.Credential" c:password="%{idp.authn.LDAP.bindDNCredential2:undefined}" />
    </property>
</bean>

<!-- Aggregate authentication -->
<bean id="aggregateAuthHandler" class="org.ldaptive.auth.AggregateDnResolver$AuthenticationHandler"
      p:authenticationHandlers-ref="authHandlers" />
<util:map id="authHandlers">
    <entry key="directory1" value-ref="authHandler1" />
    <entry key="directory2" value-ref="authHandler2" />
</util:map>

<!-- Authentication handler 1 -->
<bean id="authHandler1" class="org.ldaptive.auth.PooledBindAuthenticationHandler"
      p:connectionFactory-ref="bindPooledConnectionFactory1" />
<bean id="bindPooledConnectionFactory1" class="org.ldaptive.pool.PooledConnectionFactory"
      p:connectionPool-ref="bindConnectionPool1" />
<bean id="bindConnectionPool1" class="org.ldaptive.pool.BlockingConnectionPool" parent="connectionPool"
      p:connectionFactory-ref="bindConnectionFactory1"
      p:name="bind-pool1" />
<bean id="bindConnectionFactory1" class="org.ldaptive.DefaultConnectionFactory"
      p:connectionConfig-ref="bindConnectionConfig1" />
<bean id="bindConnectionConfig1" parent="connectionConfig"
      p:ldapUrl="%{idp.authn.LDAP.ldapURL1}" />
<!-- Authentication handler 2 -->
<bean id="authHandler2" class="org.ldaptive.auth.PooledBindAuthenticationHandler"
      p:connectionFactory-ref="bindPooledConnectionFactory2" />
<bean id="bindPooledConnectionFactory2" class="org.ldaptive.pool.PooledConnectionFactory"
      p:connectionPool-ref="bindConnectionPool2" />
<bean id="bindConnectionPool2" class="org.ldaptive.pool.BlockingConnectionPool" parent="connectionPool"
      p:connectionFactory-ref="bindConnectionFactory2"
      p:name="bind-pool2" />
<bean id="bindConnectionFactory2" class="org.ldaptive.DefaultConnectionFactory"
      p:connectionConfig-ref="bindConnectionConfig2" />
<bean id="bindConnectionConfig2" parent="connectionConfig"
      p:ldapUrl="%{idp.authn.LDAP.ldapURL2}" />

DN resolvers are invoked asynchronously, so all resolvers will be used for each authentication request.

Account State

The LDAP library used (ldaptive) has the ability to extract detailed account status information from the directory during a login. According to ldaptive documentation, no standard for exposing account state data has been universally adopted by LDAP vendors, but the ldaptive library uses a handler which encapsulates account state information. This stat