Search code examples
javaldapjndispring-ldap

spring ldap template authentication


I am trying to authenticate user via spring ldap. Following is the code to initialise ldap template.

contextSource = new LdapContextSource();
contextSource.setUrl("ldaps://ldap.example.com");
contextSource.setBase("DC=example,DC=com");
contextSource.setUserDn("backend-app");
contextSource.setPassword("password");
contextSource.afterPropertiesSet();

PoolingContextSource pooledContextSource = new PoolingContextSource(); 
pooledContextSource.setDirContextValidator(new 
DefaultDirContextValidator());
pooledContextSource.setContextSource(contextSource);

ldapTemplate =  new LdapTemplate(pooledContextSource); 
ldapTemplate.afterPropertiesSet();

When i try to use ldapTemplate authenticate method it returns false.

// below line fails
ldapTemplate.authenticate("OU=Service Accounts,OU=Pseudo-Users", "frontend-web", "password");

But when i use directory context it works

DirContext ctx = null;
try {
  ctx = contextSource.getContext("frontend-web", "password");
  return true;
} catch (Exception e) {
  logger.error("Login failed", e);
  return false;
} finally {
  LdapUtils.closeContext(ctx);  
}

Question 1 : Is there anyway to make ldaptemplate authenticate method to work?

Question 2 : Why don't we have to provide baseDn when we use DirectoryContext directly. How does ldap know where to find the user "frontend-web". Does it search the whole directory for the user "frontend-web"

Can anybody help.


Solution

  • Question 1 - I ran into the exact same issue....still haven't figured out how to use my existing LDAP template. I injected the ldap config into my service directly and created a new "private" ldapTemplate that isn't pooled, like so:

    public class AuthController {
    
        private final LdapTemplate ldapTemplate;
    
        AuthController(MyLdapConfig config) {
            LdapContextSource contextSource = new LdapContextSource();
            contextSource.setUrl(config.getUrl());
            contextSource.setUserDn(config.getUserDn());
            contextSource.setPassword(config.getPassword());
            contextSource.afterPropertiesSet();
    
            ldapTemplate = new LdapTemplate(contextSource);
            ldapTemplate.setIgnorePartialResultException(true);
        }
    
        @PostMapping
        public ResponseEntity authenticate(@RequestBody AuthenticationRequest authenticationRequest) {
            if (authenticateUser(authenticationRequest.getUsername(), authenticationRequest.getPassword())) {
                return ResponseEntity.ok().build();
            }
            log.warn("authentication failed for {}", authenticationRequest.getUsername());
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
        }
    
        // authenticateUser method omitted
    }
    

    Question 2 - yes

    the search always starts at the root of the tree (the empty path)

    https://docs.spring.io/spring-ldap/docs/2.3.1.RELEASE/reference/#basic-authentication