In this article, we will learn and build a simple web application and secure it with the Spring Security LDAP Authentication. These days LDAP Authentication is one of the most widely used approaches in enterprise-grade applications.
So, that whenever users want to access the APIs, or secured endpoints they will redirect to the login page, where authentication has to be done based on the data present in the LDAP Server.
What is LDAP?
LDAP is a protocol to access the centralized directory over an Internet Protocol Network or IP Network. A centralized directory acts as a data source, which contains all important information related to the organization such as user details, system information, etc.
It is used to sharing the information with internet application or the application which is hosted on the internet or intranet.
What is intranet application?
The intranet is a private network used by the organization, to securely communicate with the other employee and share the data over that network. So the application that develops or they used is called intranet application.
Please follow the below-mentioned steps to build and implement the LDAP Authentication in the Spring Boot Web Application.
Note: Source Code is available in the bottom section of this article.
Video Tutorial available in the bottom section.
Step 1: Create a Project from Spring Initializr.
- Go to the Spring Initializr.
- Enter a Group name, com.pixeltrice.
- Mention the Artifact Id, spring-boot-LDAP-authentication-app
- Add the Spring Web dependency.
Step 2: Click on the Generate button, the project will be downloaded on your local system.
Step 3: Unzip and extract the project.
Step 4: Import the project in your IDE such as Eclipse.
Select File -> Import -> Existing Maven Projects -> Browse -> Select the folder spring-boot-LDAP-authentication-app-> Finish.
Step 5: Create a Simple Web Controller
Since our main focus is to learn about how to implement the LDAP Authentication, so we will first create a simple web application having one endpoint. And after that, we will secure it with LDAP Authentication.
HomeController.java
package com.pixeltrice.springbootLDAPauthenticationapp;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HomeController {
@GetMapping("/")
public String index() {
return "Welcome to the Spring Security LDAP Authentication Guide!";
}
}
Since there is no view, it will simply display the message on the browser when you call this API, localhost:8080.
Up to now, we have created a very simple unsecured spring web application where anyone can able to access the controller class API without authentication.
Let’s Secure our endpoint or API.
Step 6: Add Spring Security LDAP Authentication Depencency in pom.xml
Following are the additional dependencies required for the configuration.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.unboundid</groupId>
<artifactId>unboundid-ldapsdk</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
</dependency>
unboundid-ldapsdk: It is an Open Source implementation of LDAP Server, because of this dependency the instance of LDAP Server will start running on our local system.
spring-ldap-core: It is an spring integration library which works with LDAP.
spring-security-ldap: This will provides the spring security to LDAP.
Note: These dependencies ensures that the local instance of LDAP Server is Running on our system.
But still, in the LDAP Server, we don’t have any users data, so we need to configure it in the application.properties file as shown in the next step.
Step 7: Configure the LDAP Server properties in application.properties
spring.ldap.embedded.port=8389
spring.ldap.embedded.ldif=classpath:ldap-data.ldif
spring.ldap.embedded.base-dn=dc=springframework,dc=org
spring.ldap.embedded.port: It is used to mention the port number at which embedded LDAP instance or server has to be run.
spring.ldap.embedded.ldif: This property is used to give the reference about the file which contains all the users’ data or path where all the data stored on the LDAP Server. The spring boot pulls the users’ data from the .ldif file from LDAP Server and compares it with data provided by the user at the time of login.
spring.ldap.embedded.base-dn: This is used to specify the root node of LDAP.
What is LDIF?
It is just syntax or format which is used to store the data in the LDAP Server. The full form of LDIF is the LDAP Data Interchange Format.
Step 8: Create a ldap-data.ldif file and store some data.
In this step, we will create a .ldif file and store some user’s data. You can create that file in of the location under classpath, but for simplicity, I am creating in under src/main/resources
ldap-data.ldif
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=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
Now we are good to go and configure our security policy’s.
Step 9: Configure the Spring Security LDAP Authentication
In this step we will be doing the configuration based on LDAP authentication, here we have to define which URL has to be authenticated.
SecurityConfig.java
package com.pixeltrice.springbootLDAPauthenticationapp;
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 SecurityConfig 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");
}
}
Explanation
We have extended the predefined class that is WebSecurityConfigurerAdapter, which internally implements the interface WebSecurityConfigurer. It provides us the flexibility to configure our own spring security rule. So, we have to override two methods and provide our own logic or rules for security as you can see in the above code.
- configure(HttpSecurity http){}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and()
.formLogin();
}
This method ensures that any HTTP Request must be fully authenticated before accessing our endpoints and if it is not authenticated, then it will redirect to the login page.
2. configure(AuthenticationManagerBuilder auth)
@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");
}
This method is used to tell the spring security to authenticate with LDAP Server data.
Let’s understand in the detail what each line of the code is doing.
auth.ldapAuthentication(): Here we are specifying the type of authentication we required so, we choose LDAP authentication.
.userDnPatterns(“uid={0},ou=people”): Basically Dn stands for distinguish the name, which is used to show the way in which users’ information has been stored in the LDAP Server. uid is the user id of the people present in the LDAP Server.
You can see in the .ldif file we have users information stored in following pattern.
ldap-data.ldif
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
.groupSearchBase(“ou=groups”): It will tell the spring security to start the search from users’ information from root directory groups in the LDAP Server.
.url(“ldap://localhost:8389/dc=springframework,dc=org”): URL where LDAP Server is running, and the root folder is “org”.
.passwordEncoder(new BCryptPasswordEncoder()): Password encoded in the Bycrpt format.
.passwordAttribute(“userPassword”): It represents the parameter in which the password has stored in the .ldif file in the LDAP server. If you see in the .ldif file the attribute or variable name in which the password has stored is userPassword: $2a$10$c6bSeWPhg06xB1lvmaWNNe4NROmZiSpYhlocU/98HNr2MhIOiSt36
Step 10: Run the Application
Go to localhost:8080, you will get the login screen.
Enter any of the usernames and passwords from the ldap-data.ldif file, l choose the username and password from,
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
- username is “uid”: ben
- password is in Bycrpt format, if I convert in the plain text then it is “userPassword”: benspassword
Once you Click on Sign In button, finally you able to access the secure endpoint which we have created in the controller class.
Summary
In this article, we learned how to implement the Spring Security LDAP Authentication and build a simple web application from scratch. If you any queries or doubts please feel free to ask me in the comment section.
Reference URL: https://spring.io/guides/gs/authenticating-ldap
You might also like this article.
- Payment Integration With Paytm in Spring Boot Application
- Send OTP(One Time Password) Using Spring Boot Application for Authentication
- Make a Voice Call from Spring Boot Application to Mobile Phone
- How to send email using Spring Boot Application
- Spring Boot Security using OAuth2 with JWT
- Build Spring Boot Restful CRUD API with Hibernate and Postgresql from scratch