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

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.

We will have the following steps:

  • Create a Spring boot application with required dependencies.
  • Configure embedded LDAP on created Spring boot application.
  • Retrieve the details from LDAP.
  • Running and testing the application using Postman.

We have used Spring boot version: 2.2.1.RELEASE and Java version: 1.8 on this article.

Okay!! Let’s begin!! πŸ™‚ πŸ™‚

Create a Spring boot application with required dependencies

Create a new spring boot application with required dependencies. Add spring-boot-starter-web, spring-boot-starter-data-ldap, lombok(for reducing boilerplate code) and unboundid-ldapsdk dependencies to the application.

The below pom.xml 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 configure the Spring boot application with LDAP using these properties.

Add LDAP Configurations

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

Add the below properties to 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 directory, 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.

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/ directory 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 configuration 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 DTO class called Person.java with the following fields.

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

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 LdapTemplate

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

Create an interface PersonRepo.java and add the following methods.

We will retrieve available user names, user details and fetch record 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 PersonRepoImpl.java class 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 LdapTemplate 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 used custom attribute mappers to map the result attributes into Person DTO class.

Add a controller class

Create a REST Controller class called LdapController.java 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 it 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

good job!! πŸ™‚ we have successfully configured embedded LDAP on our Spring boot application!! πŸ™‚ :-).

Conclusion

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

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

We learned how to use LdapTemplate to retrieve the records from LDAP.

Example code is available on GitHub. Happy coding!! πŸ™‚

You may also interested in