title: Spring 3.1 LDAP Authentication Process:  "Bad Credentials" msg When Credentials Are Good
body: <p>Spring 3.1
  Tomcat 6.*</p>
  
  <p>I'm working on making a Spring 3.1 webapp, authenticating with LDAP.   </p>
  
  <p>I tested the LDAP credentials (username, password, ldap URL,  search pattern ) with a JNDI styled Java program I wrote (quoted below ).  That program worked, dumped all of the users attributes, including the password, which seems to be encrypted on the LDAP server. </p>
  
  <p>When I try to login with the same credentials in Spring 3.1 I get the error message "Bad Credentials". </p>
  
  <p>I got this message in the logs:</p>
  
  <pre><code>DEBUG [org.springframework.security.authentication.ProviderManager:authenticate] (ProviderManager.java:152) - Authentication attempt using org.springframework.security.ldap.authentication.LdapAuthenticationProvider
  DEBUG [org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider:authenticate] (AbstractLdapAuthenticationProvider.java:51) - Processing authentication request for user: John.A.Smith
  DEBUG [org.springframework.security.ldap.authentication.BindAuthenticator:bindWithDn] (BindAuthenticator.java:108) - Attempting to bind as uid=John.A.Smith,ou=People,o=acme.com,o=acme.com
  DEBUG [org.springframework.security.ldap.DefaultSpringSecurityContextSource$1:setupEnvironment] (DefaultSpringSecurityContextSource.java:76) - Removing pooling flag for user uid=John.A.Smith,ou=People,o=acme.com,o=acme.com
  DEBUG [org.springframework.security.ldap.authentication.BindAuthenticator:handleBindException] (BindAuthenticator.java:152) - Failed to bind as uid=John.A.Smith,ou=People,o=acme.gov: org.springframework.ldap.AuthenticationException: [LDAP: error code 32 - No Such Object]; nested exception is javax.naming.AuthenticationException: [LDAP: error code 32 - No Such Object]
  DEBUG [org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter:unsuccessfulAuthentication] (AbstractAuthenticationProcessingFilter.java:340) - Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials
  </code></pre>
  
  <p>In my *-security.xml I tried using tags to make a password comparison and encoding happen, but it didn't help.  I tried using md4,md5,plaintext,sha,sha-256,{ssha},{sha} to no avail.   </p>
  
  <pre><code>   &lt;s:authentication-manager&gt;
          &lt;s:ldap-authentication-provider user-dn-pattern="uid={0},ou=People,o=noaa.gov" &gt;
            &lt;s:password-compare hash="md5"&gt;
              &lt;s:password-encoder hash="md5"/&gt;
            &lt;/s:password-compare&gt;
          &lt;/s:ldap-authentication-provider&gt;
        &lt;/s:authentication-manager&gt;
  </code></pre>
  
  <p>My networking group is a big, slow, bureaucratic org.  Is there a way I can tell what encoding they use, if any, without contacting them?</p>
  
  <p>Any ideas of things I could check out?</p>
  
  <p>This is my *-security.xml as of my last attempt and the java LDAP demo I WAS able to connect with</p>
  
  <p>Thanks.</p>
  
  <p><strong>My *-security.xml file:</strong></p>
  
  <pre><code>&lt;beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:s="http://www.springframework.org/schema/security"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
      http://www.springframework.org/schema/security  
      http://www.springframework.org/schema/security/spring-security-3.1.xsd"&gt;  
  
  
  
    &lt;s:http auto-config="true" use-expressions="true"&gt;  
      **&lt;s:intercept-url pattern="/welcome*" access="isAuthenticated()" /&gt;** 
      &lt;s:form-login login-page="/login" default-target-url="/welcome"  
        authentication-failure-url="/loginfailed" /&gt;  
      &lt;s:logout logout-success-url="/logout" /&gt;  
    &lt;/s:http&gt;  
  
  
  
    &lt;s:ldap-server url = "ldap://ldap-itc.sam.acme.com:636/o=acme.com"/&gt;  
  
    &lt;s:authentication-manager&gt;
      &lt;s:ldap-authentication-provider user-dn-pattern="uid={0},ou=People,o=noaa.gov" /&gt;
    &lt;/s:authentication-manager&gt;
  
  &lt;/beans&gt;  
  </code></pre>
  
  <p><strong>Here is the JNDI style LDAP Java program that WORKS with the same credentials:</strong></p>
  
  <pre><code>import javax.naming.*;  
  import javax.naming.directory.*;  
  import java.util.*;  
  import java.sql.*;  
  
  public class LDAPDEMO {  
  
      public static void main(String args[]) {  
  
          String lcf                = "com.sun.jndi.ldap.LdapCtxFactory";  
          String ldapurl            = "ldap://ldap-itc.sam.acme.com:636/o=acme.com";  
          String loginid            = "John.A.Smith";  
          String password           = "passowordforjohn";  
          DirContext ctx            = null;  
          Hashtable env             = new Hashtable();  
          Attributes attr           = null;  
          Attributes resultsAttrs   = null;  
          SearchResult result       = null;  
          NamingEnumeration results = null;  
          int iResults              = 0;  
  
  
          env.put(Context.INITIAL_CONTEXT_FACTORY, lcf);  
          env.put(Context.PROVIDER_URL, ldapurl);  
          env.put(Context.SECURITY_PROTOCOL, "ssl");  
          env.put(Context.SECURITY_AUTHENTICATION, "simple");  
          env.put(Context.SECURITY_PRINCIPAL, "uid=" + loginid + ",ou=People,o=acme.com");  
          env.put(Context.SECURITY_CREDENTIALS, password);  
          try {  
  
              ctx     = new InitialDirContext(env);  
              attr    = new BasicAttributes(true);  
              attr.put(new BasicAttribute("uid",loginid));  
              results = ctx.search("ou=People",attr);  
  
              while (results.hasMore()) {  
                  result       = (SearchResult)results.next();  
                  resultsAttrs = result.getAttributes();  
  
                  for (NamingEnumeration enumAttributes  = resultsAttrs.getAll(); enumAttributes.hasMore();) {  
                      Attribute a = (Attribute)enumAttributes.next();  
                      System.out.println("attribute: " + a.getID() + " : " + a.get().toString());  
  
  
                  }// end for loop  
  
                  iResults++;  
              }// end while loop  
  
              System.out.println("iResults == " + iResults);  
  
          }// end try  
          catch (Exception e) {  
              e.printStackTrace();  
          }  
  
  
  
      }// end function main()  
  }// end class LDAPDEMO  
  </code></pre>
  
  <hr>
  
  <p><strong>Solution</strong></p>
  
  <hr>
  
  <p>This comment from Luke Taylor helped me get my configuration working:</p>
  
  <blockquote>
    <p>Your configuration is wrong in that you have "o=acme.com" in the LDAP
    server URL and are also using "o=acme.com" in the user DN pattern.</p>
  </blockquote>
  
  <p>I took the "o=acme.com" out of the DN pattern and the LDAP worked.   I had originally put the "o=acme.com" in both the LDAP URL and the DN pattern because I am new to Spring 3.1 and LDAP, and that is similar to how it is/was done in the Java JNDI version of the LDAP demo I wrote based on the legacy code I am replacing.</p>
  
  <p>Here is the final, working version of my *-security.xml</p>
  
  <pre><code>&lt;beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:s="http://www.springframework.org/schema/security"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
      http://www.springframework.org/schema/security  
      http://www.springframework.org/schema/security/spring-security-3.1.xsd"&gt;  
  
  
  
    &lt;s:http auto-config="true" use-expressions="true"&gt;  
      **&lt;s:intercept-url pattern="/welcome*" access="isAuthenticated()" /&gt;** 
      &lt;s:form-login login-page="/login" default-target-url="/welcome"  
        authentication-failure-url="/loginfailed" /&gt;  
      &lt;s:logout logout-success-url="/logout" /&gt;  
    &lt;/s:http&gt;  
  
  
  
    &lt;s:ldap-server url = "ldap://ldap-itc.sam.acme.com:636/o=acme.com"/&gt;  
  
    &lt;s:authentication-manager&gt;
      &lt;s:ldap-authentication-provider user-dn-pattern="uid={0},ou=People" /&gt;
    &lt;/s:authentication-manager&gt;
  
  &lt;/beans&gt;  
  </code></pre>
  
  <p>I'm going to explore his other comment and see if I can put the password encoding back in or if I need to.</p>