Spring Security LDAP Authentication Example using Spring Boot Application

By | November 14, 2020

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.

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

Spring Security LDAP Authentication Example using Spring Boot Application

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
Spring Security LDAP Authentication Example using Spring Boot Application

Once you Click on Sign In button, finally you able to access the secure endpoint which we have created in the controller class.

Spring Security LDAP Authentication Example using Spring Boot Application

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.

Download the Source Code.

Reference URL: https://spring.io/guides/gs/authenticating-ldap

You might also like this article.

Leave a Reply

Your email address will not be published. Required fields are marked *