Spring Boot Embedded LDAP Example

In this article, we will learn how to use embedded LDAP with the spring boot application and retrieve the information from the embedded LDAP using the Spring framework’s LdapTemplate.

Also, we will use the UnboundID LDAP library dependency and import data from the LDIF(LDAP Data Interchange Format) file.

We will then retrieve the LDAP user data using the LdapTemplate instance.

Version details:

  • Spring boot version: 2.2.1.RELEASE
  • Java version: 1.8 on this article.

Create a Spring boot application with required dependencies

Create a new spring boot application with the required dependencies. Also, add spring boot web, spring boot data LDAP starter dependencies, Lombok(for reducing boilerplate code), and unboundid-ldapsdk dependencies to the application.

The below pom file shows all the added dependencies of our created spring boot application.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.asb.example</groupId>
	<artifactId>embedded-ldap-example</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>embedded-ldap-example</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.version>
		<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-ldap</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>com.unboundid</groupId>
			<artifactId>unboundid-ldapsdk</artifactId>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

Configure embedded LDAP on created spring boot application

Spring boot supports different configuration properties, that can be used to configure the application with the LDAP server. We will also configure the Spring boot application with LDAP using these properties.

Add LDAP Configurations

To set up LDAP with the spring boot application, we also have to add the required configurations in the application.properties file under the /resources folder.

Add the below properties to the application.properties file.

#External LDAP directory config:
#spring.ldap.urls=ldap://localhost:389
#spring.ldap.base=ou=people,dc=maxcrc,dc=com
#spring.ldap.username=cn=Manager,dc=maxcrc,dc=com
#spring.ldap.password=secret
#Embedded LDAP server config:
spring.ldap.embedded.base-dn=dc=asb,dc=com
spring.ldap.embedded.credential.username=uid=admin
spring.ldap.embedded.credential.password=secret
spring.ldap.embedded.ldif=classpath:asb-ldap.ldif
spring.ldap.embedded.port=123
spring.ldap.embedded.validation.enabled=false

Spring boot LDAP configuration properties for the external LDAP server:

  • spring.ldap.urls: External LDAP server URL along with the port.
  • spring.ldap.base: Base folder, from where the LDAP operation needs to occur.
  • spring.ldap.username: External LDAP server username.
  • spring.ldap.password: External LDAP server password.

You can set up an OpenLDAP on the local system and use it as an external LDAP server.

Also, below are the Spring boot Embedded LDAP configuration properties.

  • spring.ldap.embedded.base-dn: Base directory, from where the LDAP operation needs to occur.
  • spring.ldap.embedded.credential.username: LDAP username( default value: admin)
  • spring.ldap.embedded.credential.password: LDAP password(default value: secret)
  • spring.ldap.embedded.ldif: LDIF file path, from where the data is imported to embedded LDAP server.
  • spring.ldap.embedded.port: Port number, that the embedded LDAP server should use.
  • spring.ldap.embedded.validation.enabled: Enable/disable LDAP schema validation.

Add LDIF file

Create a file with .ldif extension under src/main/resources/ folder of the Spring boot application and add the below content.

dn: dc=asb,dc=com
objectclass: top
objectclass: domain
objectclass: extensibleObject
dc: asb
dn: ou=people,dc=asb,dc=com
objectclass: top
objectclass: organizationalUnit
ou: people
dn: uid=ben,ou=people,dc=asb,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Anne Hathaway
sn: Hathaway
uid: anne
description: Pretty Girl :-)
dn: uid=bob,ou=people,dc=asb,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: John Hamilton
sn: Hamilton
uid: john
description: Cool guy!!
dn: uid=asb,ou=people,dc=asb,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: ASB Notebook
sn: Notebook
uid: asbnotebook
description: Technical blog!.

Retrieve the details from LDAP

We have added all the configurations related to LDAP in the previous steps. Now it is time to write some code to retrieve the data from LDAP.

Create a Person DTO class

Create a java DTO class with the name Person with the below fields.

This DTO class is used to represent the LDAP record, that is retrieved using the Ldap Template.

package com.asb.example;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class Person {
	private String userId;
	private String fullName;
	private String lastName;
	private String description;
}

Retrieve LDAP record using the Ldap Template

Next, we need to retrieve the LDAP record using the LdapTemplate.

Create an interface with the name PersonRepo, and add the below methods.

Also, we will retrieve available user names, user details and fetch the records based on the user id(UID) field.

package com.asb.example;
import java.util.List;
public interface PersonRepo {
	public List<Person> getAllPersons();
	public List<String> getAllPersonNames();
	public Person getPersonNamesByUid(String userId);
}

Create a java class with the name PersonRepoImpl, and implement the PersonRepo interface.

package com.asb.example;
import static org.springframework.ldap.query.LdapQueryBuilder.query;
import java.util.List;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.stereotype.Service;
@Service
public class PersonRepoImpl implements PersonRepo {
	@Autowired
	private LdapTemplate ldapTemplate;
	@Override
	public List<String> getAllPersonNames() {
		List<String> list = ldapTemplate.search(query().where("objectclass").is("person"),
				new PersonNameAttributesMapper());
		return list;
	}
	@Override
	public List<Person> getAllPersons() {
		return ldapTemplate.search(query().where("objectclass").is("person"), new PersonAttributesMapper());
	}
	@Override
	public Person getPersonNamesByUid(String userId) {
		List<Person> people = ldapTemplate.search(query().where("uid").is(userId), new PersonAttributesMapper());
		return ((null != people && !people.isEmpty()) ? people.get(0) : null);
	}
	private class PersonAttributesMapper implements AttributesMapper<Person> {
		public Person mapFromAttributes(Attributes attrs) throws NamingException {
			Person person = new Person();
			person.setUserId(null != attrs.get("uid") ? (String) attrs.get("uid").get() : null);
			person.setFullName((String) attrs.get("cn").get());
			person.setLastName((String) attrs.get("sn").get());
			person.setDescription(null != attrs.get("description") ? (String) attrs.get("description").get() : null);
			return person;
		}
	}
	private class PersonNameAttributesMapper implements AttributesMapper<String> {
		public String mapFromAttributes(Attributes attrs) throws NamingException {
			return attrs.get("cn").get().toString();
		}
	}
}

In the above example, we are using the Ldap Template to search the LDAP directory. We have also used the LDAP query() method to search the LDAP directory by filtering the result based on different attributes.

We have also used custom attribute mappers to map the result attributes into the Person DTO class.

Add a controller class

Create a REST Controller java class with the name LdapController, and expose RESTful endpoints to retrieve the LDAP records.

package com.asb.example;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LdapController {
	@Autowired
	private PersonRepo personRepo;
	
	@GetMapping("/get-user-names")
	public ResponseEntity<List<String>> getLdapUserNames() {
		return new ResponseEntity<>(personRepo.getAllPersonNames(), HttpStatus.OK);
	}
	@GetMapping("/get-users")
	public ResponseEntity<List<Person>> getLdapUsers() {
		return new ResponseEntity<>(personRepo.getAllPersons(), HttpStatus.OK);
	}
	@GetMapping("/get-user")
	public ResponseEntity<Person> findLdapPerson(@RequestParam(name = "user-id") String userId) {
		return new ResponseEntity<>(personRepo.getPersonNamesByUid(userId), HttpStatus.OK);
	}
}

Running and testing the application using Postman

We will use the Postman tool to check the exposed endpoints.

Retrieve user names

This endpoint retrieves all the available usernames available in LDAP.

LDAP Retrieve usernames

Retrive LDAP objects

This endpoint retrieves different fields available in LDAP and maps them into the Person DTO.

LDAP Retrieve All available user details

Retrieve Person object based on a field value

In this endpoint, we pass the user-id(uid field of LDAP) to retrieve the LDAP record.

LDAP retrieve user details by UID

Finally, we have successfully configured embedded LDAP on our Spring boot application!.

Conclusion

In this article, we learned how to configure the Spring boot application and retrieve the LDAP data from the configured LDAP server.

We have also learned how to configure the spring boot applications with an external LDAP server using the application configuration properties.

Finally, we learned how to use LdapTemplate to retrieve the records from LDAP.

The example code is available on GitHub. Happy coding!! 🙂