Chapter 10. User Authentication using Spring LDAP

While the core functionality of the ContextSource is to provide DirContext instances for use by LdapTemplate, it may also be used for authenticating users against an LDAP server. The getContext(principal, credentials) method of ContextSource will do exactly that; construct a DirContext instance according to the ContextSource configuration, authenticating the context using the supplied principal and credentials.

Example 10.1. Using ContextSource for user authentication

public boolean authenticate(String userDn, String credentials) {
  DirContext ctx = null;
  try {
    ctx = contextSource.getContext(userDn, credentials);
    
    return true;
  } catch (Exception e) {
    // Context creation failed - authentication did not succeed
	logger.error("Login failed", e);
    return false;
  } finally {
    // It is imperative that the created DirContext instance is always closed
    LdapUtils.closeContext(ctx);
  }
}

Note

The userDn supplied to the authenticate method needs to be the full DN of the user to authenticate (regardless of the base setting on the ContextSource). You will typically need to perform an LDAP search based on e.g. the user name to get this DN:

Example 10.2. Finding a user based on uid attribute.

private String getDnForUser(String uid) {
  Filter f = new EqualsFilter("uid", uid);
  List result = ldapTemplate.search(DistinguishedName.EMPTY_PATH, f.toString(), new AbstractContextMapper() {
    protected Object doMapFromContext(DirContextOperations ctx) {
      return ctx.getNameInNamespace();
    }
  });
  	
  if(result.size() != 1) {
    throw new RuntimeException("User not found or not unique");
  }
  
  return (String)result.get(0);
}

Note

Some authentication schemes and LDAP servers require some operation to be performed on the created DirContext instance for the actual authentication to occur. You should test and make sure how your server setup and authentication schemes behave; failure to do so might result in that users will be admitted into your system regardless of the DN/credentials supplied.

Example 10.3. Performing LDAP operation on returned DirContext objects.

public boolean authenticate(String userDn, String credentials) {
  DirContext ctx = null;
  try {
    ctx = contextSource.getContext(userDn, credentials);
    // Take care here - if a base was specified on the ContextSource
    // that needs to be removed from the user DN for the lookup to succeed.
    ctx.lookup(userDn);
    
    return true;
  } catch (Exception e) {
    // Context creation failed - authentication did not succeed
	logger.error("Login failed", e);
    return false;
  } finally {
    // It is imperative that the created DirContext instance is always closed
    LdapUtils.closeContext(ctx);
  }
}

Note

While the approach above may be sufficient for very simple authentication scenarios, requirements in this area commonly expand rapidly. There is a multitude of aspects that apply to this area, including authentication, authorization, web integration, user context management, etc. If you suspect that the requirements might expand you should definitely consider using Spring Security for your security purposes instead. It is a full-blown, mature security framework addressing the above aspects as well as several others.