Spring Security LDAP Authentication Example java Security Spring Spring Boot by devs5003 - August 1, 2024September 30, 20240 Last Updated on September 30th, 2024If you have ever implemented login feature in a production grade application, you must have heard about the LDAP authentication. LDAP can be used in any type of the hierarchical directory information. The most popular use of LDAP is to store an organizational data. A typical organization generally has directors, managers, supervisors and other positions. In other words, these are the hierarchical data where LDAP mechanism is perfect to implement. In this way, most of the organizations use it to maintain the organizational information including their credentials. We will discuss Spring Security LDAP Authentication Example in this article. In Spring based applications, LDAP is used to integrate with LDAP directories and perform various directory-related operations, such as user authentication and authorization. Spring provides tools and libraries to work with LDAP smoothly, making it a popular choice for developing applications that require LDAP integration. Table of Contents Toggle What is LDAP?How does LDAP work?What is LDIF?What are the common fields in an LDIF file?What is the format of an LDIF file?How to implement Spring Security LDAP Authentication Example Using Spring Boot?Use-case DetailsStep#1: Create a Spring Boot Starter Project using STSStep#2: Create a .ldif file as ldap-data.ldifStep#3: Update application.properties fileStep#4: Create a Controller class for basic authenticationLoginController.javaStep#5A: Create a Configuration class as LdapSecurityConfig.javaLdapSecurityConfig.javaStep#5B: Create a Configuration class as LdapSecurityConfig.java Without WebSecurityConfigurerAdapterHow to test the Application?FAQsAre there any alternatives to LDAP for user management in Spring Boot?Can we use LDAP in combination with other authentication mechanisms in Spring Boot?Conclusion What is LDAP? LDAP stands for Lightweight Directory Access Protocol. It is an open, vendor-neutral, industry standard application protocol to access and maintain distributed directory information services over the network. How does LDAP work? As aforementioned, LDAP stores the user’s information of an organization. When a user tries to login to an application, it checks with LDAP to see if it is a valid user and if that user has required rights & valid credentials. In the context of Spring Security, the application connects to the LDAP server in order to verify the valid user against that LDAP. LDAP integration in Spring is valuable for organizations that already use LDAP directories for user management and want to extend this infrastructure to secure and manage their Spring based applications. It simplifies user management and enhances the security and authorization capabilities of Spring based applications. What is LDIF? LDIF is an abbreviation for LDAP Data Interchange Format. It is a standard plain text data interchange format of a file that is used for representing LDAP directory content. The extension of the file is ‘.ldif’. There are multiple fields in the LDIF file. Let’s know about them: What are the common fields in an LDIF file? 1) dn : distinguished name ‘dn’ represents the name that uniquely identifies an entry in the directory. DN is a mandatory field. If there is a comma in the DN, the comma must be escaped with a backslash (\). For example, dn: uid=sam, ou=people, o=example.com Bolivia\,S.A. 2) o : organization ‘o’ represents the organization name. For example: google.com 3) dc : domain component ‘dc’ represents each component of the domain. For example www.example.com would be written as DC=www, DC=example, DC=com 4) ou : organizational unit ‘ou’ represents the organizational unit (or sometimes the user group) that the user is part of. If the user is part of more than one group, you may specify it by providing multiple entries. For example: OU= employee, OU= admin. 5) cn : common name ‘cn’ represents the individual object (person’s name; meeting room; recipe name; job title; etc.) for whom/which you are querying. It is commonly used by the person. For example, cn: Bill Anderson. At least one common name is required. 6) sn : surname ‘sn’ represents the person’s surname, or last name. For example, sn: Anderson. A surname is required. 7) objectClass : object class ‘objectClass’ specifies an object class to use with this entry.. It is a mandatory field. For example: objectClass: person, objectClass: organizationalPerson. This object class specification should be included because many LDAP clients require it during search operations for a person or an organizational person. You may refer oracle doc Object Class Reference for a list of standard object classes. What is the format of an LDIF file? LDIF consists of one or more directory entries separated by a blank line. Each LDIF entry consists of an optional entry ID, a required distinguished name, one or more object classes, and multiple attribute definitions. The LDIF format is defined in RFC 2849 The LDAP Data Interchange Format (LDIF). Sun Java System Directory Server is compliant with this standard. The basic form of a directory entry represented in LDIF is as follows: dn: distinguished_name objectClass: object_class objectClass: object_class ... attribute_type[;subtype]:attribute_value attribute_type[;subtype]:attribute_value ... We must supply the DN and at least one object class definition. In addition, we must include any attributes required by the object classes that we define for the entry. All other attributes and object classes are optional. We can specify object classes and attributes in any order. The space after the colon is also optional. For example, below is a valid entry in an LDIF file. Here field ‘uid’ stands for user id of the person. dn: uid=bob,ou=people,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson cn: Bob Hamilton sn: Hamilton uid: bob userPassword: bobspassword How to implement Spring Security LDAP Authentication Example Using Spring Boot? Spring Security, a widely used security framework in Spring Boot, provides LDAP support for user authentication and authorization, making it clear-cut to secure our application using LDAP. Use-case Details Let’s assume that we have an application where we have already implemented basic security using the Spring Security API provide by Spring Framework. Now we have to implement LDAP authentication in order to make user’s interaction more secure. Therefore, we need to develop a basic web application and then implement LDAP authentication concepts to fulfil the requirements of Spring Security LDAP Authentication Example. Let’s develop  Spring Security LDAP Authentication Example Using Spring Boot step by step as below: Step#1: Create a Spring Boot Starter Project using STS Here, we are using STS (Spring tool Suite) as an IDE to develop the example. While creating Starter Project select ‘Spring Web’, ‘Spring LDAP’, ‘Embedded LDAP Server’, ‘Spring security’ and ‘Spring Boot DevTools’ as starter project dependencies. Here ‘Spring Boot Dev Tools’ is optional to add. We are using Spring Boot Dev Tools to avoid restarting tomcat server multiple times while testing the application. Apart from that, we need to add one additional dependency of ‘spring-security-ldap’. Even If you don’t know how to create Spring Boot Starter Project, Kindly visit a separate article on How to create a starter project Using Spring Boot?. Below are the dependencies that we have used to develop this Spring Security LDAP Authentication Example Using Spring Boot. <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-ldap</artifactId> </dependency> <dependency> <groupId>com.unboundid</groupId> <artifactId>unboundid-ldapsdk</artifactId> <!-- <scope>test</scope> --> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-ldap</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> Step#2: Create a .ldif file as ldap-data.ldif This file will have a mandatory ‘.ldif’ extension. Create a file named ‘ldap-data.ldif’ under the folder src/main/resources and update the data as shown below. We have taken this file from Spring Official documentation website. It will work as local directory and have compatible data to work with LDAP accordingly. dn: dc=springframework,dc=org objectclass: top objectclass: domain objectclass: extensibleObject dc: springframework dn: ou=groups,dc=springframework,dc=org objectclass: top objectclass: organizationalUnit ou: groups dn: ou=subgroups,ou=groups,dc=springframework,dc=org objectclass: top objectclass: organizationalUnit ou: subgroups dn: ou=people,dc=springframework,dc=org objectclass: top objectclass: organizationalUnit ou: people dn: ou=space cadets,dc=springframework,dc=org objectclass: top objectclass: organizationalUnit ou: space cadets dn: ou=\"quoted people\",dc=springframework,dc=org objectclass: top objectclass: organizationalUnit ou: "quoted people" dn: ou=otherpeople,dc=springframework,dc=org objectclass: top objectclass: organizationalUnit ou: otherpeople dn: uid=ben,ou=people,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Ben Alex sn: Alex uid: ben userPassword: $2a$10$c6bSeWPhg06xB1lvmaWNNe4NROmZiSpYhlocU/98HNr2MhIOiSt36 dn: uid=admin,ou=people,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Admin sn: Admin uid: admin userPassword: $2a$10$ODZhWAyD0i8zruWQcMYx9ePkW2xXsqIljhh4K8spSOUCY897ERkwu dn: uid=bob,ou=people,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Bob Hamilton sn: Hamilton uid: bob userPassword: bobspassword dn: uid=joe,ou=otherpeople,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Joe Smeth sn: Smeth uid: joe userPassword: joespassword dn: cn=mouse\, jerry,ou=people,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Mouse, Jerry sn: Mouse uid: jerry userPassword: jerryspassword dn: cn=slash/guy,ou=people,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: slash/guy sn: Slash uid: slashguy userPassword: slashguyspassword dn: cn=quote\"guy,ou=\"quoted people\",dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: quote\"guy sn: Quote uid: quoteguy userPassword: quoteguyspassword dn: uid=space cadet,ou=space cadets,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Space Cadet sn: Cadet uid: space cadet userPassword: spacecadetspassword dn: cn=developers,ou=groups,dc=springframework,dc=org objectclass: top objectclass: groupOfUniqueNames cn: developers ou: developer uniqueMember: uid=ben,ou=people,dc=springframework,dc=org uniqueMember: uid=bob,ou=people,dc=springframework,dc=org dn: cn=managers,ou=groups,dc=springframework,dc=org objectclass: top objectclass: groupOfUniqueNames cn: managers ou: manager uniqueMember: uid=ben,ou=people,dc=springframework,dc=org uniqueMember: cn=mouse\, jerry,ou=people,dc=springframework,dc=org dn: cn=submanagers,ou=subgroups,ou=groups,dc=springframework,dc=org objectclass: top objectclass: groupOfUniqueNames cn: submanagers ou: submanager uniqueMember: uid=ben,ou=people,dc=springframework,dc=org Here, we have highlighted one user’s data that we will use to test the implemented example. Step#3: Update application.properties file In this file we will have some properties of our embedded LDAP as shown below. spring.ldap.embedded.port=8389 spring.ldap.embedded.ldif=classpath:ldap-data.ldif spring.ldap.embedded.base-dn=dc=springframework,dc=org Step#4: Create a Controller class for basic authentication Next step is to create a RestController class. When we enter the credentials in order to login to the application, we will see a successful login message. Let’s create a simple controller LoginController.java as below. LoginController.java package com.dev.springboot.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class LoginController { @GetMapping("/") public String getLoginPage() { return "You have successfully logged in Using Spring Security LDAP Authentication!"; } } Step#5A: Create a Configuration class as LdapSecurityConfig.java This is the configuration class where we will keep the whole logic of LDAP Authentication as shown below. LdapSecurityConfig.java import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @Configuration public class LdapSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().fullyAuthenticated() .and() .formLogin(); } @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth .ldapAuthentication() .userDnPatterns("uid={0},ou=people") .groupSearchBase("ou=groups") .contextSource() .url("ldap://localhost:8389/dc=springframework,dc=org") .and() .passwordCompare() .passwordEncoder(new BCryptPasswordEncoder()) .passwordAttribute("userPassword"); } } Note: If you are working with Spring Security 5.7.0-M2 or later, you are not supposed to use WebSecurityConfigurerAdapter. In that case, kindly visit a separate article on ‘Spring Security Without WebSecurityConfigurerAdapter‘. You can also take help of the below code in Step#5B for reference. The implementation is done without using WebSecurityConfigurerAdapter. Step#5B: Create a Configuration class as LdapSecurityConfig.java Without WebSecurityConfigurerAdapter import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.ldap.DefaultSpringSecurityContextSource; import org.springframework.security.ldap.authentication.BindAuthenticator; import org.springframework.security.ldap.authentication.LdapAuthenticationProvider; import org.springframework.security.ldap.search.FilterBasedLdapUserSearch; import org.springframework.security.web.SecurityFilterChain; @Configuration public class LdapSecurityConfig { protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests() .anyRequest().fullyAuthenticated() .and() .formLogin(); http.authenticationProvider(ldapAuthenticationProvider()); return http.build(); } @Bean LdapAuthenticationProvider ldapAuthenticationProvider() { return new LdapAuthenticationProvider(authenticator()); } @Bean BindAuthenticator authenticator() { FilterBasedLdapUserSearch search = new FilterBasedLdapUserSearch("ou=groups", "(uid={0})", contextSource()); BindAuthenticator authenticator = new BindAuthenticator(contextSource()); authenticator.setUserSearch(search); return authenticator; } @Bean public DefaultSpringSecurityContextSource contextSource() { DefaultSpringSecurityContextSource dsCtx = new DefaultSpringSecurityContextSource("ldap://localhost:8389/dc=springframework,dc=org"); dsCtx.setUserDn("uid={0},ou=people"); return dsCtx; } } How to test the Application? In order to test the application, we need to open a browser and hit the URL http://localhost:8080/. On hitting the URL, the default login page will get displayed. Further, enter any credentials given in the ldap-data.ldif file. If inserted credentials are correct, you will see the successful login message using LDAP Authentication. For example, let’s observe the below user’s data in the ldap-data.ldif file. dn: uid=admin,ou=people,dc=springframework,dc=org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Admin sn: Admin uid: admin userPassword: $2a$10$ODZhWAyD0i8zruWQcMYx9ePkW2xXsqIljhh4K8spSOUCY897ERkwu Here, aid is the username and userpassword is the encrypted value of password. The real value of password is ‘admin@123’. Hence, we need to provide admin@123 as a password. Once you click on Sign In button, you should see the message ‘You have successfully logged in Using Spring Security LDAP Authentication!’ on the screen. We can use below Utility class to encode any password. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; public class PasswordEncoder { public static void main(String[] args) { System.out.println(new BCryptPasswordEncoder().encode("admin@123")); } } FAQs Are there any alternatives to LDAP for user management in Spring Boot? Yes, Spring Boot offers support for various authentication and user management mechanisms, including database-backed authentication, OAuth2, and more. The choice depends on your application’s requirements and existing infrastructure. Can we use LDAP in combination with other authentication mechanisms in Spring Boot? Yes, we can combine LDAP authentication with other authentication mechanisms, such as OAuth2, in Spring Boot applications. This allows us to provide multiple authentication options to users. Conclusion In this article we have covered all the theoretical and example part of ‘Spring Security LDAP Authentication Example Using Spring Boot’, finally, you should be able to implement Spring Security LDAP Authentication. Similarly, we expect from you to further extend this example, as per your requirement. Also try to implement it in your project accordingly. Moreover, Feel free to provide your comments in the comments section below. Related