Skip to content
Advertisement

Spring Boot REST API using LDAP authentication

So I’m trying to build a REST API that will use LDAP authentication. Basically, when my login endpoint is consumed, I want it to detect credentials using httpBasic authentication and then use those credentials against my LDAP server. I also want to take into account user roles, protecting endpoints so that only certain users with the proper roles can access said endpoints.

Is it possible to do this? In my readings so far, I haven’t seen a tutorial or article that clearly states how to implement this.

*UPDATE: I managed to configure it to be able to accept credentials using httpBasic. Now I would like to know how to set permissions for specific endpoints using user roles based on LDAP groups (e.g. managers, developers)

Advertisement

Answer

This can actually be accomplished pretty succinctly with Spring Boot.

pom.xml

<?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.3.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.so</groupId>
    <artifactId>rest-ldap</artifactId>
    <version>1.0.1</version>
    <name>rest-ldap</name>
    <description>SO REST LDAP Solution</description>

    <properties>
        <java.version>11</java.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-ldap</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

App.java

package com.so;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@EnableWebSecurity
@RestController
@SpringBootApplication
public class App extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .httpBasic()
                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .csrf()
                .disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder
                .ldapAuthentication()
                .contextSource()
                .url("ldap://ldap-server.com:3268")
                .managerDn("CN=MGR_USERNAME")
                .managerPassword("MGR_PASSWORD")
                .and()
                .userSearchFilter("CN={0}");
    }

    @RequestMapping
    public Authentication getAuth() {
        return SecurityContextHolder.getContext().getAuthentication();
    }

    public static void main(String[] args) {
        SpringApplication.run(com.so.App.class, args);
    }

}

Send request http://USERNAME:PASSWORD@localhost:8080

Receive (successful) response

HTTP/1.1 200
Set-Cookie: JSESSIONID=COOKIE-VALUE; Path=/; HttpOnly
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Content-Type: application/json
Transfer-Encoding: chunked
Date: Mon, 01 Jan 1970 00:00:00 GMT
{
  "authorities": [],
  "details": {
    "remoteAddress": "127.0.0.1",
    "sessionId": null
  },
  "authenticated": true,
  "principal": {
    "dn": "cn=USERNAME",
    "password": null,
    "username": "USERNAME",
    "authorities": [],
    "accountNonExpired": true,
    "accountNonLocked": true,
    "credentialsNonExpired": true,
    "enabled": true,
    "timeBeforeExpiration": 2147483647,
    "graceLoginsRemaining": 2147483647
  },
  "credentials": null,
  "name": "USERNAME"
}

Enjoy!

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement