Archive for the ‘Spring Security’ Category

This article will guide you in setting up LDAP Authentication in your web project using Spring Security.

Step 1: Setup Spring Security

To configure Spring Security, you first need to add some extra dependencies to your build.

For a Gradle-based build, add these dependencies to your build.gradle

dependencies {
    compile("org.springframework.security:spring-security-core")
    compile("org.springframework.security:spring-security-web")
    compile("org.springframework.security:spring-security-config")
    compile("org.springframework.security:spring-security-taglibs")
    compile("org.springframework.security:spring-security-ldap")
}

For a Maven-based build, add these dependencies to your pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactIdspring-security-config</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-taglibs</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-ldap</artifactId> </dependency> </dependencies>

 

Step 2 : Get LDAP Connection Parameters

Check with your system administrator what the LDAP credentials should be:

  • LDAP_SERVER_URL: The LDAP url to connect to. (example: “ldap://localhost:389/”)
  • MANAGER_DN: The principal to perform the initial bind to the LDAP server. (example: “cn=admin,ou=people,dc=suhasjavablog,dc=com”)
  • MANAGER_PASSWORD: The credentials to perform the initial bind to the LDAP server. (example: “secret”)
  • USER_SEARCH_FILTER: The LDAP filter to determine the LDAP dn for the user that’s logging in, {0} will be replaced with the username that’s logging in (example: “((uid={0})(objectClass=inetOrgPerson))”)
  • USER_SEARCH_BASE: The LDAP filter that is the base for searching for users (example: “dc=suhasjavablog,dc=com”)
  • Create a properties file with all these paramaters and place it in classpath

ldapConfig.properties

## LDAP Integration
LDAP_SERVER_URL=ldap://localhost:10389/dc=suhasjavablog,dc=com
MANAGER_DN=uid=admin,ou=people,dc=suhasjavablog,dc=com
MANAGER_PASSWORD=secret
USER_SEARCH_BASE=dc=suhasjavablog,dc=com
USER_SEARCH_FILTER=(sAMAccountName={})

Step 3 : Validate the LDAP Connection parameters using command line util – ldapsearch

Step 3 : Create a spring security configuration xml

Create a file applicationContext-security.xml in your project and import that that file in your Spring applicationContext.xml

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
  <import resource="applicationContext-security.xml"/>

applicationContext-security.xml

Since this article is about ldap authentication using spring security, i am ommiting the irrelevant entries for ease of understanding.

  • Configure Spring to use an LDAP Server
    • Spring Security supports authentication against LDAP through LdapAuthenticationProvider, an authentication provider that knows how to check user credentials against and LDAP repository.
<ldap-server id="contextSource" url="${LDAP_SERVER_URL}"
    manager-dn="${MANAGER_DN}" manager-password="${MANAGER_PASSWORD}"/>
  • Authenticating with LDAP binding
    • Spring Security comes with an LdapAuthenticator implementation called BindAuthenticator. (In our example, we are using BindAuthenticator)
    • Bindauthenticator uses an LDAP bind operator to bind as a user to the LDAP server.
    • This approach relies on the LDAP server to authenticate the user’s credentials.
<beans:bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
    <beans:constructor-arg>
        <!-- the bind authenticator will first lookup the user using the service account credentials, then
             attempt to bind the user with their password once found -->
        <beans:bean id="bindAuthenticator" class="org.springframework.security.ldap.authentication.BindAuthenticator">
            <beans:constructor-arg ref="contextSource" />
            <beans:property name="userSearch" ref="userSearch" />
        </beans:bean>
    </beans:constructor-arg>
<!-- We have defined a custom ldap authorities populator -->
    <beans:constructor-arg ref="customLdapAuthoritiesPopulator"/>
</beans:bean>
  • Alternative Approach : Authenticating by comparing passwords
    • Spring Security also supports authentication by password comparison with PasswordComparisonAuthenticator.
    • PasswordComparisonAuthenticator compares the supplied password with a password attribute (userpassword, by default) in the user record.
    • The password is encoded using the password encoder, by default LdapShaPasswordEncoder.
    • Unlike BindAuthenticator, PasswordComparisonAuthenticator doesn’t bind to LDAP using the user’s DN.
    • It is fine if your LDAP provider allows anonymous binding. Otherwise, you will need to provide a userDN and password.
  • Declaring the populator
    • Once the user identity is confirmed, LdapAuthenticationProvider must retrieve a list of the user’s granted authorities.
    • Spring Security comes with DefaultLdapAuthoritiesPopulator. Here’s how a default populator is configured:
<beans:bean id="populator"
            class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
    <beans:constructor-arg ref="contextSource" />
    <!--  group based DN - we will be searching for groups in "ou=groups,dc=example,dc=com" -->
    <beans:constructor-arg value="ou=groups" />

    <!-- the name of the attribute that will contain role information (which
         effectively translates to a user's granted authorities. Default is "cn" -->
    <beans:property name="groupRoleAttribute" value="ou" />

    <!-- case normalization to upper case. Default is true -->
    <beans:property name="convertToUpperCase" value="false" />

    <!-- role prefix to append to the group name. Default is "ROLE_". -->
    <beans:property name="rolePrefix" value="" />
</beans:bean>
  • In our example, we are using a custom ldapAuthoritiesPopulator as our roles are stored in database.
<beans:bean id="customLdapAuthoritiesPopulator" 
class="com.suhasjavablog.security.CustomLdapAuthoritiesPopulator"/>
public class CustomLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator {

    @Autowired
    private UserService userService;

    @Override
    public Collection<? extends GrantedAuthority> getGrantedAuthorities(DirContextOperations userData, String username) {
        User user = userService.searchByUserName(username);
        Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
        if (null != user) {
           //implement your logic to fetch roles from database in this service layer method
            authorities.addAll(userService.getGrantedAuthorities(user));
        }
        return authorities;
    }
}

The final applicationContext-security.xml is given below with only the authentication related configurations.

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/security
   http://www.springframework.org/schema/security/spring-security-3.1.xsd">
    
      
     <beans:bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <beans:property name="location">
            <beans:value>classpath:ldapConfig.properties</beans:value>
        </beans:property>
    </beans:bean>

    <ldap-server id="contextSource" url="${LDAP_SERVER_URL}"
                 manager-dn="${MANAGER_DN}" 
                 manager-password="${MANAGER_PASSWORD}"/>

    <beans:bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
        <beans:constructor-arg>
          <!-- the bind authenticator will first lookup the user using the service account credentials, then
           attempt to bind the user with their password once found -->
            <beans:bean id="bindAuthenticator" class="org.springframework.security.ldap.authentication.BindAuthenticator">
                <beans:constructor-arg ref="contextSource" />
                <beans:property name="userSearch" ref="userSearch" />
            </beans:bean>
          </beans:constructor-arg>
          <beans:constructor-arg ref="customLdapAuthoritiesPopulator"/>
        </beans:bean>

        <beans:bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
            <beans:constructor-arg index="0" value="${USER_SEARCH_BASE}" />
            <beans:constructor-arg index="1" value="${USER_SEARCH_FILTER}" />
            <beans:constructor-arg index="2" ref="contextSource" />
            <beans:property name="searchSubtree" value="true" />
        </beans:bean>

        <beans:bean id="customLdapAuthoritiesPopulator" class="com.suhasjavablog.security.CustomLdapAuthoritiesPopulator"/>

        <!-- AUTHENTICATION CONFIGURATIONS FOR HOW USER WILL BE AUTHENTICATED -->
        <authentication-manager alias="authenticationManager" erase-credentials="false">
            <authentication-provider ref="ldapAuthProvider"/>
        </authentication-manager>
       
</beans:beans>

 

Like & Support if  this article helped you !

 

 

Advertisements