Open In App

Spring Security with LDAP Authentication

Last Updated : 20 Sep, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

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.

Project Metadata

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:

Project Folder Structure

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).

Apache DS Directory
  • 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:



Next Article

Similar Reads