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. A custom
    authenticate method could look like this:
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);
  }
}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:
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);
}There are some drawbacks to this approach. The user is forced to concern herself with the DN of the user, she can only search for the user's uid, and the search always starts at the root of the tree (the empty path). A more flexible method would let the user specify the search base, the search filter, and the credentials. Spring LDAP 1.3.0 introduced new authenticate methods in LdapTemplate that provide this functionality:
boolean authenticate(Name base, String filter, String
        password);
boolean authenticate(String base, String filter, String
        password);
Using one of these methods, authentication becomes as simple as this:
Example 10.1. Authenticating a user using Spring LDAP.
boolean authenticated = ldapTemplate.authenticate("", "(uid=john.doe)", "secret");
        
| ![[Note]](images/note.png) | Note | 
|---|---|
| As described in below, some setups may require additional operations to be performed in order for actual authentication to occur. See Section 10.2, “Performing Operations on the Authenticated Context” for details. | 
| ![[Tip]](images/tip.png) | Tip | 
|---|---|
| Don't write your own custom authenticate methods. Use the ones provided in Spring LDAP 1.3.x. | 
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. This is a naïve implementation of an authenticate
    method where a hard-coded lookup operation is performed
    on the authenticated context:
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);
  }
}It would be better if the operation could be provided as an
    implementation of a callback interface, thus not limiting the operation to
    always be a lookup. Spring LDAP 1.3.0 introduced the
    callback interface
    AuthenticatedLdapEntryContextCallback and a few
    corresponding authenticate methods:
boolean authenticate(Name base, String filter, String
        password, AuthenticatedLdapEntryContextCallback
        callback);
boolean authenticate(String base, String filter, String
        password, AuthenticatedLdapEntryContextCallback
        callback);
This opens up for any operation to be performed on the authenticated context:
Example 10.2. Performing an LDAP operation on the authenticated context using Spring LDAP.
AuthenticatedLdapEntryContextCallback contextCallback = new AuthenticatedLdapEntryContextCallback() {
  public void executeWithContext(DirContext ctx, LdapEntryIdentification ldapEntryIdentification) {
    try {
      ctx.lookup(ldapEntryIdentification.getRelativeDn());
    }
    catch (NamingException e) {
      throw new RuntimeException("Failed to lookup " + ldapEntryIdentification.getRelativeDn(), e);
    }
  }
};
ldapTemplate.authenticate("", "(uid=john.doe)", "secret", contextCallback));So far, the methods have only been able to tell the user whether or
    not the authentication succeeded. There has been no way of retrieving the
    actual exception. Spring LDAP 1.3.1 introduced the
    AuthenticationErrorCallback and a few more
    authenticate methods:
boolean authenticate(Name base, String filter, String
        password, AuthenticationErrorCallback errorCallback);
boolean authenticate(String base, String filter, String
        password, AuthenticationErrorCallback errorCallback);
boolean authenticate(Name base, String filter, String
        password, AuthenticatedLdapEntryContextCallback callback,
        AuthenticationErrorCallback errorCallback);
boolean authenticate(String base, String filter, String
        password, AuthenticatedLdapEntryContextCallback callback,
        AuthenticationErrorCallback errorCallback);
A convenient collecting implementation of the error callback interface is also provided:
public final class CollectingAuthenticationErrorCallback implements AuthenticationErrorCallback {
  private Exception error;
  public void execute(Exception e) {
    this.error = e;
  }
  public Exception getError() {
    return error;
  }
}The code needed for authenticating a user and retrieving the authentication exception in case of an error boils down to this:
Example 10.3. Authenticating a user and retrieving the authentication exception.
import org.springframework.ldap.core.support.CollectingAuthenticationErrorCallback;
...
CollectingAuthenticationErrorCallback errorCallback = new CollectingAuthenticationErrorCallback();
boolean result = ldapTemplate.authenticate("", filter.toString(), "invalidpassword", errorCallback);
if (!result) {
  Exception error = errorCallback.getError();
  // error is likely of type org.springframework.ldap.AuthenticationException
}While the approach above may be sufficient for simple authentication scenarios, requirements in this area commonly expand rapidly. There is a multitude of aspects that apply, including authentication, authorization, web integration, user context management, etc. If you suspect that the requirements might expand beyond just simple authentication, 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.