Java – Spring LDAP authentication without using admin/manager account

active-directoryjavaldapspring

my requirement is to authenticate user's login (username & password) to be able to access the web application.

Using Java, i was able to authenticate using the user's provided login:

boolean isCredentialsValid = false;

Hashtable env = new Hashtable();        
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapUrl);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, username);
env.put(Context.SECURITY_CREDENTIALS, password);

try {
 DirContext ctx = new InitialDirContext(env);
 ctx.close();
 isCredentialsValid = true;
} catch (Exception e) {
 e.printStackTrace(); 
}

System.out.println(isCredentialsValid);

Can this be directly implemented in Spring? Like using BindAuthenticator or PasswordComparisonAuthenticator? I tried using this configuration:

<bean id="contextSource"
 class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
   <constructor-arg value="IP of LDAP Server:389" />
</bean>

<bean id="ldapAuthenticator"
 class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator">
  <constructor-arg ref="contextSource"/>
  <property name="userDNPatterns" >
  <list>
   <value>uid={0}, dc=company,dc=com</value>
  </list>
  </property>
</bean>

<bean id="userSearch"
 class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
  <constructor-arg index="0" value="ou=people" />
  <constructor-arg index="1" value="(uid={0})" />
  <constructor-arg index="2" ref="contextSource" />
  <property name="searchSubtree" value="true" />
</bean>

But i'm encoutering UncategorizedLdapException.

From what I've read on Spring LDAP so far, I cannot directly authenticate user's login without providing a admin account.

Any help is very much appreciated!

This is the stacktrace:

Uncategorized exception occured during LDAP processing; nested exception is javax.naming.NamingException: [LDAP: error code 1 – 000004DC: LdapErr: DSID-0C0906DC, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v1db0]; remaining name 'uid=username@company.com'; nested exception is org.springframework.ldap.UncategorizedLdapException: Uncategorized exception occured during LDAP processing; nested exception is javax.naming.NamingException: [LDAP: error code 1 – 000004DC: LdapErr: DSID-0C0906DC, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v1db0]; remaining name 'uid=username@company.com'

Best Answer

The LdapTemplate (spring-ldap-core 1.3.1RELEASE) is useless in this scenario(to bad, I believe it is useless for others as well)- since on the LdapTemplate.authenticate(...) method performs a search, which obviously can not be completed without a successfull binding first.

I adapted the same concept like in the ActiveDirectoryLdapAuthenticationProvider:

  1. Authenticating against the LDAP with the old fashion way

    private static DirContext bindAsUser(String username, String password) {
      final String bindUrl = url;
    
      Hashtable<String, String> env = new Hashtable<String, String>();
      env.put(Context.SECURITY_AUTHENTICATION, "simple");
      String bindPrincipal = username;
      env.put(Context.SECURITY_PRINCIPAL, bindPrincipal);
      env.put(Context.PROVIDER_URL, bindUrl);
      env.put(Context.SECURITY_CREDENTIALS, password);
      env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    
      try {
        return contextFactory.createContext(env);
      } catch (NamingException e) {
        throw new RuntimeException(e);
      }
    }  
    
  2. Using the SpringSecurityLdapTemplate for quering the LDAP

Another issue with the spring-ldap-core 1.3.1RELEASE, I can not understand why it was not merged to spring-security-ldap: 3.1.

Related Topic