LDAP Authentication Handler
Including the Handler
In the pom.xml file for your CAS webapp (the default is ${project.home}/cas-server-webapp/pom.xml) add the following dependency:
<dependency> <groupId>${project.groupId}</groupId> <artifactId>cas-server-support-ldap</artifactId> <version>${project.version}</version> </dependency>
Core Classes
You need to decide how you would like CAS to authenticate the credentials. Should it merely attempt to authenticate to (bind to) the LDAP server using the credentials directly as the user? Or should it first look up the user in some subtree and then attempt to bind as that user? It is more efficient and more secure to use fastbind, but that is not always possible. This is explained in detail later in this document.
Both methods require you to configure an LDAP context bean: this is the configuration to access your directory. It is recommended to configure a new bean in the top list and reference that from the configuration of the AuthenticationHandler, as explained in the instructions on this page.
FastBindLdapAuthenticationHandler
This is the most straight-forward implementation of LDAP authentication. It simply tries to bind to the directory with the credentials provided by the user. Since the user is not aware of the LDAP tree, you have to configure the handler to try and bind to a certain preconfigured node. This means you can only use this method if you are able to configure the user's node in advance. Else you'll need to use the search-and-bind method (explained below).
The FastBindLdapAuthenticationHandler supports the following properties:
- filter - The filter property is the LDAP filter that will be used for the search. When constructing the filter, wherever you want the username to appear, place a "%u".
- ignorePartialResultException - This property informs Spring LDAP to ignore PartialResultExceptions that may get thrown when connecting to an Active Directory.
- contextSource - This is a reference to a AuthenticatedLdapContextSource (see below) which will contain the settings for connecting to the LDAP server.
BindLdapAuthenticationHandler
This method first does a general search for the user before it tries to bind to the directory. When it finds the user it attempts to do a bind with the DN that resulted from the search and the password from the user's submitted credentials. Note that for this method you will need a special user that is allowed to search the directory (OR allow anonymous access to search the directory).
- filter - The filter property is the LDAP filter that will be used for the search. When constructing the filter, wherever you want the username to appear, place a "%u".
- ignorePartialResultException - This property informs LdapTemplate to ignore PartialResultExceptions that may get thrown when connecting to an Active Directory.
- contextSource - This is a reference to a AuthenticatedLdapContextSource (see below) which will contain the settings for connecting to the LDAP server.
- allowMultipleAccounts - Allows more than one account to be returned.
- maxNumberOfResults - this is the maximum number of results we allow.
- scope - One of the predefined "SearchControl" Scopes: SearchControls.OBJECT_SCOPE, SearchControls.ONELEVEL_SCOPE, or SearchControls.SUBTREE_SCOPE
- searchBase - The search base is the node in the directory from where the search will be performed.
- timeout - This is the amount of time we are willing to wait for the search results to return.
AuthenticatedLdapContextSource
This class is an extension of Spring LDAP's LdapContextSource. Its extended to allow it to retrieve specific DirContexts while re-using existing environment settings. Its additional method is modeled after the Java DataSource.
The LdapContextSource defines some important properties, listed below (note some of this is copied directly from the JavaDocs):
- anonymousReadOnly - Set to false if an authenticated environment should be created for read-only operations.
- baseEnvironmentProperties - If any custom environment properties are needed, these can be set using this method.
- password - Set the password (credentials) to use for getting authenticated contexts.
- pooled - Set whether the pooling flag should be used. Note that even if pooling is set, the additional method provided by AuthenticatedLdapContextSource will not use pooling.
- url or urls - the url(s) to the LDAP server. Specifying a list of servers automatically configures redundancy so it is highly recommended to do so. Port 636 is the typical LDAP SSL port, 389 is the standard LDAP port. Java SDK v1.4.2+ interprets correctly ldap:// or ldaps:// without specifying the port. If you're using an older JDK you cannot specify the ldaps:// protocol so you'll need to explicitly define a port and set the protocol to SSL in the environment properties.
- userName - the username (principal) for getting authenticated contexts.
Please note that the JVM needs to trust the certificate of your SSL enabled LDAP server, else CAS will refuse to connect to your LDAP server. You can add the LDAP server's certificate to the JVM trust store ($JAVA_HOME/jre/lib/security/cacerts) to solve that issue.
Configuration
Note that all configuration should happen in the deployerConfigContext.xml in the webapp module.
Set up the AuthenticatedLdapContextSource
Within the <beans>...</beans>, place your AuthenticatedLdapContextSource bean. Your configuration will look like this:
<bean id="contextSource" class="org.jasig.cas.adaptors.ldap.util.AuthenticatedLdapContextSource"> <property name="pooled" value="true"/> <property name="urls"> <list> <value>ldaps://ldap.rutgers.edu/</value> <value>ldaps://ldap2.rutgers.edu/</value> </list> </property> <property name="userName" value="{bind_username_goes_here}"/> <property name="password" value="{bind_user_password_goes_here}"/> <property name="baseEnvironmentProperties"> <map> <entry> <key> <value>java.naming.security.authentication</value> </key> <value>simple</value> </entry> </map> </property> </bean>
NOTE: You may or may not have all these properties set. This is just an example.
Remember, the Active Directory object Users is a cn, not an ou. So if you're connecting to AD then your configuration will look like this:
<bean id="contextSource" class="org.jasig.cas.adaptors.ldap.util.AuthenticatedLdapContextSource"> <property name="urls"> <list> <value>ldaps://yourdc.yourdomain.edu/</value> </list> </property> <property name="userName" value="{cn=bind_user_goes_here,cn=Users,dc=yourdomain,dc=edu}"/> <property name="password" value="{bind_user_password_goes_here}"/> <property name="baseEnvironmentProperties"> <map> <entry> <key> <value>java.naming.security.authentication</value> </key> <value>simple</value> </entry> </map> </property> </bean>
Note: You should explicitly set the java.naming.security.authentication environment property to "simple" for the userName and password to be used. If there is no java.naming.security.authentication environment property specified, it will default to "none". This means the directory will always be accessed as "anonymous". This is most useful in the Fast Bind scenario.
Specifying a list of servers automatically configures redundancy so it is highly recommended to do so.
Port 636 is the typical LDAP SSL port, 389 is the standard LDAP port. Java SDK v1.4.2+ interprets correctly ldap:// or ldaps:// without specifying the port. If you're using an older JDK you cannot specify the ldaps:// protocol so you'll need to explicitly define a port and set the protocol to SSL in the environment properties.
Please note that the JVM needs to trust the certificate of your SSL enabled LDAP server, else CAS will refuse to connect to your LDAP server. You can add the LDAP server's certificate to the JVM trust store ($JAVA_HOME/jre/lib/security/cacerts) to solve that issue.
Set Up the *LdapAuthenticationHandlers.
Both Ldap Authentication Handlers are set up in almost the same way (just different class names and properties), so we're only going to show one here.
This AuthenticationHandler is configured as a bean within the authenticationHandlers property on the authenticationManager. You'll most likely want to remove the test authentication handler there, and replace it with something like this:
<bean class="org.jasig.cas.adaptors.ldap.BindLdapAuthenticationHandler"> <property name="filter" value="uid=%u" /> <property name="searchBase" value="ou=people,dc=rutgers,dc=edu" /> <property name="contextSource" ref="contextSource" /> </bean>
For connecting to MS-AD these settings will look like this (note: in this case all users are in the "Users" branch):
<bean class="org.jasig.cas.adaptors.ldap.BindLdapAuthenticationHandler"> <property name="filter" value="sAMAccountName=%u" /> <property name="searchBase" value="cn=Users,dc=yourdomain,dc=edu" /> <property name="contextSource" ref="contextSource" /> <property name="ignorePartialResultException" value="yes" /> <!-- fix because of how AD returns results --> </bean>
To use the FastBind LDAP Handler, you would configure something like this:
<property name="authenticationHandlers"> <list> <!-- | This is the authentication handler that authenticates services by means of callback via SSL, thereby validating | a server side SSL certificate. +--> <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"> <property name="httpClient" ref="httpClient" /> </bean> <!-- | This is the authentication handler declaration that every CAS deployer will need to change before deploying CAS | into production. | With this configuration you'll be using LDAP FastBind authentication. +--> <bean class="org.jasig.cas.adaptors.ldap.FastBindLdapAuthenticationHandler" > <property name="filter" value="uid=%u,ou=people,dc=rutgers,dc=edu" /> <property name="contextSource" ref="contextSource" /> </bean> </list> </property>