Spring Security with LDAP Authentication
Last Updated :
20 Sep, 2024
LDAP (Lightweight Directory Access Protocol) is widely used for identity and access management. It organizes data in a hierarchical structure, optimized for read-heavy operations. LDAP is advantageous due to its scalability and interoperability. In this article, we will create a simple authentication system using Spring Security with LDAP.
Prerequisites:
To follow along, you will need:
Steps to Implement LDAP in Spring Security
Step 1: Create a Spring Boot Project
Go to Spring Initializr and select:
- Group:
com.example
- Artifact:
ldap-demo
- Dependencies: Spring Web, Spring Security, Spring LDAP, Spring Boot DevTools
Download the project and extract the zip file.
Step 2: Add LDAP Dependency
Open the pom.xml
file and add the Spring Security LDAP dependency if not already present.
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-ldap -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
<version>6.3.3</version>
</dependency>
Also install the dependencies by running the command in your terminal at your project location:
mvn install
Project Structure:
Create the following files inside the src directory of the project:
- LdapController.java
- LdapService.java
- SecurityConfig.java
- UserDTO.java
Create the HTML files named addUser.html and success.html inside the resources/static folder. After creating the above-mentioned files your project structure will look like this:
Step 4: Define Code Files
Now, let’s go through the code files with explanations and inline comments.
4.1 LdapController.java
This controller handles the endpoints for displaying the home page and managing user creation.
Java
// LdapController.java
package org.geeksforgeeks.ldap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class LdapController {
@Autowired
LdapService ldapService;
@GetMapping("/")
@ResponseBody // This is used to override the default behaviour of @Controller Annotation to return HTML pages.
public String homePage() {
return "Welcome to home page!"; // This text will be only visible to authenticated users.
}
@GetMapping("/add-user")
public String addUser() {
return "addUser.html"; // Custom form page to take inputs from users and create them.
}
// We will be receiving data from the HTML page and create a user object to generate LDAP user using LdapService.
@PostMapping(path="/add-user", consumes="application/x-www-form-urlencoded")
public String generateUser(@RequestParam Map<String, String> body) {
UserDTO userDTO = new UserDTO(body.get("email"), body.get("commonName"), body.get("surname"), body.get("password"));
ldapService.createUser(userDTO);
return "redirect:/add-user";
}
}
Explanation:
- The
LdapController
manages the endpoints /
(for home) and /add-user
(for user creation). - The
LdapService
handles the actual user creation process in LDAP.
4.2 LdapService.java
This service class interacts with LDAP to create new users.
Java
//LdapService.java
package org.geeksforgeeks.ldap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.stereotype.Service;
@Service
public class LdapService {
@Autowired
private LdapTemplate ldapTemplate;
// Create a entry in the LDAP server
public void createUser(UserDTO userDTO){
ldapTemplate.bind("userid="+userDTO.getEmail()+",ou=users,ou=system", null, userDTO.toAttributes());
}
}
Explanation:
- The
LdapService
uses LdapTemplate
to create and bind a new user to the LDAP directory using the given user details. - The
createUser()
method constructs the Distinguished Name (DN) and sets attributes like email, common name, surname, and password.
4.3 UserDTO.java
This class represents a Data Transfer Object for user details.
Java
// UserDTO.java
package org.geeksforgeeks.ldap;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttributes;
// Data Transfer Object for LDAP user
public class UserDTO{
UserDTO(String email, String commonName, String surname, String password){
this.commonName = commonName;
this.email = email;
this.surname = surname;
this.password = password;
}
public String getEmail() {
return this.email;
}
public String getCommonName() {
return this.commonName;
}
public String getSurname() {
return this.surname;
}
public String getPassword() {
return this.password;
}
private String email;
private String commonName;
private String surname;
private String password;
public Attributes toAttributes(){
Attributes attributes = new BasicAttributes();
attributes.put("objectClass","inetOrgPerson");
attributes.put("cn",commonName);
attributes.put("sn",surname);
attributes.put("userPassword",password);
return attributes;
}
}
Explanation:
- This is a simple DTO class that holds user details, including email, common name, surname, and password. This data is passed between layers of the application.
4.4 SecurityConfig.java
This class configures Spring Security to use LDAP authentication.
Java
//SecurityConfig.java
package org.geeksforgeeks.ldap;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.ldap.LdapBindAuthenticationManagerFactory;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig{
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().fullyAuthenticated() // All requests to all endpoints need authentication
)
.formLogin(Customizer.withDefaults())
.csrf(AbstractHttpConfigurer::disable); // Disable CSRF protection
return http.build();
}
@Bean
public LdapContextSource contextSource() {
LdapContextSource ldapContextSource = new LdapContextSource();
ldapContextSource.setUrl("ldap://localhost:10389"); // URL of our LDAP server
ldapContextSource.setUserDn("uid=admin,ou=system"); // Distinguishable Node of Admin
ldapContextSource.setPassword("secret"); // Password of Admin
return ldapContextSource;
}
@Bean
public LdapTemplate ldapTemplate() {
return new LdapTemplate(contextSource()); // Template used for creating new users
}
@Bean
AuthenticationManager authenticationManager(BaseLdapPathContextSource source){
LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(source);
factory.setUserDnPatterns("userid={0},ou=users,ou=system"); // Location of our user directory
return factory.createAuthenticationManager();
}
}
Explanation:
SecurityConfig
defines Spring Security settings, including access rules and LDAP authentication configurations.- The LDAP server details, including the user DN pattern and admin credentials, are specified here.
4.5 addUser.html
This HTML form allows for user creation in the LDAP directory.
HTML
<!-- addUser.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Add User</title>
<style>
body{
margin: 0;
padding: 0;
font-family: 'Helvetica';
background-color: #ededed;
}
form{
font-size:1.5rem;
max-width: 330px;
padding: 15px;
margin: 0 auto;
}
h2{
margin-bottom:20px;
}
#container{
max-width: 1140px;
margin-right: auto;
margin-left: auto;
padding-right: 15px;
padding-left: 15px;
width: 100%;
}
input{
display:block;
width:308px;
border:1px solid #cccccc;
font-size:16px;
padding:13px 10px 13px 10px;
border-radius:.25rem;
margin-bottom: 16px;
}
input[type="submit"]{
background-color: #007bff;
border-color: #0062cc;
color:white;
font-weight:400;
font-size:20px;
border:none;
width: 100%;
height: 50px;
border-radius: .3rem;
}
</style>
</head>
<body>
<div id="container">
<form method="post">
<h2>Add User</h2>
<input type="email" name="email" placeholder="Email Address">
<input name="commonName" placeholder="First Name">
<input name="surname" placeholder="Surname">
<input type="password" name="password" placeholder="Password">
<input type="submit">
</form>
</div>
</body>
</html>
Explanation:
- This HTML form collects user data (email, common name, surname, and password) and submits it to the
/add-user
endpoint for processing.
4.6 success.html
A simple success page shown after a user is added.
HTML
<!-- success.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Success</title>
</head>
<body>
<h1>User added successfully</h1>
</body>
</html>
Explanation:
- Displays a message to indicate that the user has been successfully added to the LDAP directory.
Step 5: Run the Application
- Before running the spring boot application make sure to install Apache Directory Server and Apache Directory Studio on your computer.
- After installation, open the Apache Directory Studio and make a new connection to the LDAP server (Apache Directory Server).
- Your LDAP server will be running on port 10389, make sure to provide all the necessary information while making the connection request.
Note: We have not set the password for the admin account, and the default password will be "secret" (without the double quotes).
- After establishing the connection with LDAP server, we can see the directory as shown above. We will try to add users to OU (Organizational Unit) = users.
- We need to create at least one user using Apache Directory Studio so that we can add more users through the spring boot application by visiting "/add-user" endpoint.
Step 6: Create an Initial User in LDAP via Apache Directory Studio
Create a user by right-clicking on ou=users -> New -> New Entry -> Create entry from scratch.
- Search for inetOrgPerson in the search bar and add that object.
- Some additional objects will be added along with it automatically.
- Select the RDN (Relative Distinguishable Name) as userid and provide a value (must be unique).
- After that click on next and add CN (Common Name) and SN (Surname) since it is a required field for inetOrgPerson object.
- Add an additional attribute named userPassword and choose SSHA as Hash Method.
Step 7: Run the Spring Boot Application
Now start the spring boot application and go to http://localhost:8080/. You will prompted to provided username and password. Provide the credentials of the previously created user to view the page.
Output Video:
Step 9: Access and Test the Application
Now we can add more users to the application which will be stored in the ou=users, ou=system directory of our LDAP server. Provide the necessary details and click on submit button and a user will be created with the appropriate information.
Output Video: