Archive for the ‘LDAP’ 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

In this article, we will consider one of the main LDAP utilities – ldapsearch. It’s a shell-accessible interface that opens a connection to the specified LDAP server using the specified distinguished name and password and locates entries base on a specific search filter, parameters and options.

Query Ldap server and extract information

Below three commands will query and extract all entries from LDAP server

ldapsearch -x -h ldap://suhasjavablog.ad.com -p 389

-x stands for simple authentication (without SASL)
-h specifies hostname
-p used for port (that can be 636 in case of LDAP over SSL)

ldapsearch -x -h ldap://suhasjavablog.ad.com:389                                                                                -D “cn=manager,dc=suhasjavablog,dc=com” -W

-D defines bind Distinguish name. In other words, your authentication user DN for primary binding with LDAP Server
-W will prompt for bind password

If you want, you can even mention the password along with the user name

ldapsearch -x -h ldap://suhasjavablog.ad.com:389                                                                                  -D “cn=manager,dc=suhasjavablog,dc=com” -w “plainTextPassword”

-w will use the password provided in the command line

Query SSL / TLS

In order to use LDAP Uniform Resource Identifier (URI), you need to user -H flag that specifies a URI to use to connect to the server and port in the following format: ldap[s]://hostname[:port]

ldapsearch -x -H ldap://suhasjavablog.ad.com   

ldapsearch -x -H ldaps://suhasjavablog.ad.com   

The port is optional, it will use default LDAP of 389 or LDAPS port of 636 if the port is not given. The output will be all your LDAP database.

All the above commands will list down all the entries from the ldap server.

Search Specific Base DN and Scope

ldapsearch -H ldap://suhasjavablog.ad.com                                                                                       -D “cn=manager,dc=suhasjavablog,dc=com” -w “plaintextPassword”                       -b “ou=people,dc=suhasjavablog,dc=com” -s base

-b defines base distinguish name for search. In other words, it defines starting point for the search
-s scope of your search. That can be base object (base), one-level (one), subtree (sub) or children search (children)

The output of the command above will be the base distinguish name of ou=people,dc=suhasjavablog,dc=com scope.

In case of the same base dn and subtree scope search you will get everything (all subtrees) that goes under the ou=users,ou=department,dc=suhasjavablog,dc=com tree.

ldapsearch -H ldap://suhasjavablog.ad.com                                                                                       -D “cn=manager,dc=suhasjavablog,dc=com” -w “plaintextPassword”                       -b “ou=people,dc=suhasjavablog,dc=com” -s sub

Search for a User

Lets see how to search for user with uid = Mesut.Ozil

ldapsearch -H ldap://suhasjavablog.ad.com                                                                                       -D “cn=manager,dc=suhasjavablog,dc=com” -w “plaintextPassword”                        -b “ou=people,dc=suhasjavablog,dc=com” -s sub ‘uid=Mesut.Ozil’

The output will as follows

# search result
search: 2
result: 0 Success

# numResponses: 5
# numEntries: 1
# numReferences: 3

The output says thats the search is successful and numEntries = 1 , which means it found one match against the uid ‘Mesut.Ozil’. If no match is found, then the numEntries won’t be displayed on the output.

 

Introduction to LDAP Basics

Posted: April 19, 2018 in LDAP
Tags: , , , , ,

 

What is LDAP?

  • LDAP stands for Lightweight Directory Access Protocol.
  • It is a standard for storing and accessing “Directory” information.
  • OpenLDAP (unix) and Active Directory (Microsoft) implement LDAP.
  • Commonly used to store organisational information such as employee information.
  • Queried for access control definitions such as logging in, checking access etc.

How is information stored?

  • LDAP is a hierachical (tree-based) database.
  • Information is stored as key-value pairs.
  • The tree structure is basically free-form. Every organisation can choose how to arrange the tree for themselves, although there are some commonly used patterns.
  • Each entry is identified by its distinguished name (DN).

The tree

An sample LDAP tree structure would be as follows

Tree

  • Each leaf in the tree has a specific unique path called the Distinguished Name (DN).
    For example: uid=Suhas,ou=people,dc=suhasjavablog,dc=com
  • Unlike file paths and most other tree-based paths which have their roots on the left, the Distinguished Name has the root of the tree on the right.
  • Instead of the conventional path separators such as the dot ( . ) or forward-slash ( / ), the DN uses the comma ( , ) to separate path elements.
  • Unlike conventional paths (e.g. /com/suhasjavablog/people/Suhas), the DN path includes an attribute type for each element in the path. For instance: dc=, ou= and uid=. These are abbreviations that specify the type of the attribute.
  • It is common to arrange the tree in a globally unique way, using dc=com,dc=suhasjavablog to specify the organisation.
  • Entries are parts of the tree that actually store information. In this case: uid=Suhas and uid=Mesut.

Entries

  • An entry has an Relative Distinguished Name (RDN).
  • The RDN is a unique identifier for the entry in that part of the tree.

Lets look at the entry for the DN uid=Suhas,ou=people,dc=suhasjavablog,dc=com on the above tree.

tree 1

  • For this entry, the RDN is uid=Suhas.
  • An entry stores key/value pairs. In LDAP lingo, these are called attribute types and attribute values.
  • Attribute types are sometimes abbreviations. In this case, the attribute types are cn= (CommonName), uid= (UserID) and mail=.Keys may appear multiple times, in which case the are considered as a list of values.
  • An entry has one or more objectClasses. It is defined as ‘objectClass: value’ when included in an Entry.
  • Object classes are defined by schemas, and they determine which attributes must and may appear in an entry. For instance, the organizationalPerson object class is defined in the nis.schema and must include cn, uid, etc.
  • Different object classes may define the same attribute types.

Follow my blog to get notified about upcoming posts on