Posted In: Spring, Spring Boot, Spring Security

Example – Spring Boot – Security – Integrating With LDAP

 

 

1. Create Spring boot project. Refer create-eclipse-spring-boot-application-step-by-step

 
 

2. Choose LDAP checkbox or add following maven entry

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

 
 

3a. Add unboundid maven entry for testing with in memory LDAP. Example is using unboundid

<dependency>
	<groupId>com.unboundid</groupId>
	<artifactId>unboundid-ldapsdk</artifactId>
</dependency>

 
 

3b. Add entry to application.properties

spring.ldap.embedded.base-dn: dc=javausecase,dc=com
logging.level.org.springframework.web=DEBUG
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

 
 

3c. In case you do not want to use in-memory LDAP, for your own LDAP server add entry to application.properties

spring.ldap.urls=ldap://localhost:1235
spring.ldap.username=admin
spring.ldap.password=secret

 
 

4. Load test data in LDAP. Create schema.ldif file under CLASSPATH

dn: dc=javausecase,dc=com
objectclass: top
objectclass: domain
objectclass: extensibleObject
dc: javausecase

dn: ou=groups,dc=javausecase,dc=com
objectclass: top
objectclass: organizationalUnit
ou: groups

dn: ou=subgroups,ou=groups,dc=javausecase,dc=com
objectclass: top
objectclass: organizationalUnit
ou: subgroups

dn: ou=people,dc=javausecase,dc=com
objectclass: top
objectclass: organizationalUnit
ou: people

dn: uid=abhijit,ou=people,dc=javausecase,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Abhijit Pednekar
sn: Abhijit
uid: abhijit
userPassword: abcd123

 
 

5. Use LdapTemplate to authenticate user

package com.example.springapp;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.query.LdapQuery;
import org.springframework.ldap.query.LdapQueryBuilder;
import org.springframework.stereotype.Component;

@Component
public class AuthLdap {
	private final LdapTemplate ldapTemplate;
	final static Logger logger = LoggerFactory
	        .getLogger(AuthLdap.class);

	@Autowired
	public AuthLdap(LdapTemplate ldapTemplate) {
		this.ldapTemplate = ldapTemplate;
	}

	public void verifyCredentials(String userId,
	        String password) {
		System.out.println("inside verifyCredentials() userId="
		        + userId + "::password=" + password);
		LdapQuery query = LdapQueryBuilder.query().where("uid")
		        .is(userId);

		ldapTemplate.authenticate(query, password);
	}
}

 
 

6. Create simple login FORM

<!DOCTYPE html>
<html>
<head>
<script
	src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

<script>
function ldapAuthenticate() {
	var userData = {"userId" : "", "userPassword" : ""};
	userData.userId = $('#userId').val();
	userData.userPassword = $('#userPassword').val();
	
	$.ajax({
		type : "POST",
		url : "/ldap/user/auth",
		data : JSON.stringify(userData),
        contentType: 'application/json',
		success : function(msg) {
			alert("success");
		},
		error : function() {
			alert("failure");
		}
	});
}	
</script>
</head>
<body>
	<h1>Example - Spring Boot LDAP Authentication</h1>

	<form method="POST" action="/">
		User ID :  <input type="text" name="userId" id="userId"/><br /> 
		Password : <input type="password" name="userPassword" id="userPassword"/><br /> 
		<br /> <input type="button" value="Submit" onClick="ldapAuthenticate();"/>
	</form>

</body>
</html>

 
 

7. Create service “/ldap/user/auth”

package com.example.springapp;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class LdapService {

	@Autowired
	AuthLdap authLdap;

	@RequestMapping(value = "/ldap/user/auth",
	        consumes = "application/json",
	        method = { RequestMethod.POST })
	public @ResponseBody Object ldapAuthenticate(
	        ServletRequest req, ServletResponse res,
	        @RequestBody String requestJson) throws Exception {
		System.out.println("ldapAuthenticate() called");
		System.out.println("requestJson=" + requestJson);
		JSONObject json = new JSONObject(requestJson);
		String userId = json.getString("userId");
		String password = json.getString("userPassword");
		authLdap.verifyCredentials(userId, password);
		return "{'response' : 'success'}";
	}

	@RequestMapping("/")
	public String index(Map<String, Object> model) {
		System.out.println("index() called");
		model = new HashMap<String, Object>();
		return "login";
	}
}

 
 

8. Test

 

8a. Test in browser

 
Use user id abhijit and password abcd123 for testing

 
 

8b. Test with Rest Template Client

 

package com.example.springapp;

import org.junit.Test;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;

public class Example201722ApplicationTests2 {
	@Test
	public void testBasicAuth2() throws Exception {
		try {
			String url = "http://localhost:8080/ldap/user/auth";
			RestTemplate rest = new RestTemplate(
			        new HttpComponentsClientHttpRequestFactory());
			rest.getMessageConverters().add(
			        new MappingJackson2HttpMessageConverter());
			rest.getMessageConverters()
			        .add(new StringHttpMessageConverter());
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			HttpEntity<String> entity = new HttpEntity<String>(
			        "{'userId' : 'abhijit', 'userPassword' : 'abcd123'}",
			        headers);
			ResponseEntity<String> response = rest.exchange(url,
			        HttpMethod.POST, entity, String.class);
			System.out.println(response.getBody());
		} catch (HttpStatusCodeException e) {
			e.printStackTrace();
			if (e.getStatusCode() == HttpStatus.UNAUTHORIZED) {
				String responseString = e
				        .getResponseBodyAsString();
				System.out.println(responseString);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 
 

8c. Test with CURL

 

curl -X POST http://localhost:8080/ldap/user/auth --header "Content-Type:application/json" -d "{'userId' : 'abhijit', 'userPassword' : 'abcd123'}"

 

 
 

Tags: , , ,

by , on February 18th, 2017

  • Categories