title: Spring security 3.1 ldap
body: <p>I am trying to authenticate to an ldap server using spring security 3.1.</p>
  
  <p>I have zero to very little knowledge of ldap.</p>
  
  <p>In the old code  , which is around 7years old. we have a servlet calling a login object as </p>
  
  <pre><code>  mypackage.Login login = new mypackage.Login("*******",
                            "389",
                            "none",
                            "cn",
                            "ou=Employees, ou=**, o=ny, c=US",
                            "ou=Employees, ou=**, o=ny, c=US",
                            v);
     String[] res = login.authenticate(username, password);
  </code></pre>
  
  <p>The Login code is as:</p>
  
  <pre><code>package mypackage;
  
  import java.util.Hashtable;
  import java.util.Enumeration;
  import java.util.Vector;
  import java.util.StringTokenizer;
  import java.lang.*;
  import java.util.regex.*;
  import javax.naming.*;
  import javax.naming.directory.*;
  import mypackage.LoginErrorBean;
  
  import javax.naming.NamingException;
  
  public class Login 
  {
    private static String INITCTX = "com.sun.jndi.ldap.LdapCtxFactory";
  
    private String host;
    private String port;
    private String encryption;
    private String mgrdnattrib;
    private String mgrdnpath;
    private String searchbase;
    private Vector attribs;
  
    private LoginErrorBean myErrors = new LoginErrorBean();
  
    public Login() {}
  
    public Login(String host,String port,String encryption,String mgrdnattrib,String mgrdnpath,String searchbase,Vector attribs) 
  
    {
      // Parameter settings to connect to desired LDAP service.
      // Note: the encryption piece does not seem to work at all
      this.host = host;
      this.port = port;
      this.encryption = encryption;
      this.mgrdnattrib = mgrdnattrib;
      this.mgrdnpath = mgrdnpath;
      this.searchbase = searchbase;
      this.attribs = attribs;
    }
  
    public String[] authenticate(String username, String password) throws NamingException
    {
       String[] authenticate;
            authenticate = new String [5];
  
      //Set default authentication code to false, f. Authentication is considered valid if value other than 'f' is returned for [0]
            authenticate[0] = "f";
  
      try {
        String MGR_DN = mgrdnattrib + "="  + username.toUpperCase() + "," + mgrdnpath;
        String MGR_PW = password;
        String provider = "ldap://" + host + ":" + port;
  
        // Parse atributes
        String MY_ATTRS[] = new String[attribs.size()];
        for (int i = 0; i &lt; attribs.size(); ++i) {MY_ATTRS[i] = (String)attribs.get(i);}
  
        // Specify the search filter to match for general users
        String MY_FILTER ="("+ mgrdnattrib+"=*)";
  
        Hashtable env = new Hashtable();
  
        // Specify which class to use for our JNDI provider
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, provider);
        env.put(Context.SECURITY_AUTHENTICATION,"simple");
        env.put(Context.SECURITY_PRINCIPAL,MGR_DN);
        env.put(Context.SECURITY_CREDENTIALS,MGR_PW);
  
        if ( encryption.toUpperCase().compareTo("SSL") == 0 ) {env.put(Context.SECURITY_PROTOCOL,"ssl");}
  
        // Specify host and port to use for directory service
  
        // Get a reference to a directory context
        DirContext ctx = new InitialDirContext(env);
  
        // Specify the scope of the search
        SearchControls constraints = new SearchControls();
        constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
  
        // Perform the actual search
        // We give it a searchbase, a filter and a the constraints
        // containing the scope of the search
        NamingEnumeration results = ctx.search(searchbase,MY_FILTER, constraints);
  
        Attribute fn = null;
        Attribute last = null;
        Attributes res = null;
        Attribute ou = null;
        Attribute tel = null;
        Attribute rm = null;
        String givenname = "";
        String ln = "";
        String area = "";
        String phone = "";
        String room = "";
  
          if (results != null &amp;&amp; results.hasMore()) {
  
            SearchResult sr = (SearchResult) results.next();
  
            //Attempt to retrieve the ou
            try 
            {  res = sr.getAttributes();
               ou = res.get("ou");
               area = ou.toString();            
            } catch (Exception ex) {ex.printStackTrace();} 
            finally {}
  
            area.trim();
  
            //Given name
            try 
            { fn = res.get("givenname");
              givenname = fn.toString();
              givenname = givenname.replaceAll("givenName:","");
              givenname = givenname.trim();
              authenticate[1]=givenname;
            } catch (Exception ex) {ex.printStackTrace();} 
            finally {}
  
            //sn
            try 
            { last = res.get("sn");
              ln = last.toString();
              ln = ln.replaceAll("sn:","");
              ln = ln.trim();
              authenticate[2]= ln;
            } catch (Exception ex) {ex.printStackTrace();} 
            finally {}
  
            //Phone
            try 
            { tel = res.get("telephonenumber");
              phone = (tel.toString()==null?"No Phone":tel.toString());
              if(phone.length()==0)
              {phone="telephoneNumber:None";}
            phone = phone.replaceAll("telephoneNumber:","");
            phone = phone.trim();
            authenticate[3]= phone;
            } catch (Exception ex) {ex.printStackTrace();} 
            finally {}
  
            //Room
            try 
            { rm = res.get("l");
              room = rm.toString();
             if(room.length()==0)
              {room="l:None";}
            room = room.replaceAll("l:","");
            room = room.trim();
            authenticate[4]= room;
            } catch (Exception ex) {ex.printStackTrace();} 
            finally {}
            authenticate [0] = "u";
            /**
             * This section appears to check again, confirming that the username for login is the same login name found in LDAP. 
             * It seems like this is repetitive, will maintain for now however. 10/30/06 axk
            */
  
        }
  
      } catch (Exception e) {
          System.err.println("Exception: " + e.getMessage());
          authenticate[1] = e.getMessage();
          myErrors.addErrorMessage(e.toString());
  
      }
      return authenticate;
    }
  }
  </code></pre>
  
  <p>I am trying to do this in spring security file as:
  </p>
  
  <pre><code>                    &lt;s:ldap-authentication-provider user-search-filter="(uid={0})"
                      user-search-base="ou=Employees, ou=***, o=ny, c=US"/&gt;
  
  
  &lt;/s:authentication-manager&gt;
  
      &lt;s:ldap-server id="ldapServer" url="ldap://****:389" manager-dn="cn={0},ou=Employees, ou=nysed, o=ny, c=US" manager-password="{1}" /&gt;
  </code></pre>
  
  <p>Is this the right way ,
  i am not sure if </p>
  
  <pre><code>manager-dn="cn={0},ou=Employees, ou=nysed, o=ny, c=US" manager-password="{1}" 
  </code></pre>
  
  <p>is right in the security config file.</p>
  
  <p>I am trying to implement this in spring ( its there in Login class file shown above)
        String MGR_DN = mgrdnattrib + "="  + username.toUpperCase() + "," + mgrdnpath;
        String MGR_PW = password;</p>
  
  <p>is manager-password="{1}" the right way to specify that manager password is same as user provided password. ?</p>
  
  <p>When I am tring to authenticate using a user-name provided that worked for the java code , I get an error.</p>
  
  <pre><code>&lt;AbstractAuthenticationProcessingFilter&gt; &lt;doFilter&gt; An internal error occurred while trying to authenticate the user.
  org.springframework.security.authentication.InternalAuthenticationServiceException: [LDAP: error code 49 - 8009030C: LdapErr: DSID-0C0903AA, comment: AcceptSecurityContext error, data 2030, v1772
  at org.springframework.security.ldap.authentication.LdapAuthenticationProvider.doAuthentication(LdapAuthenticationProvider.java:191)
      at org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:61)
      at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
      at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
      at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
      at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:195)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
      at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
      at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
      at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
      at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
      at oracle.security.jps.ee.http.JpsAbsFilter$1.run(JpsAbsFilter.java:111)
      at java.security.AccessController.doPrivileged(Native Method)
      at oracle.security.jps.util.JpsSubject.doAsPrivileged(JpsSubject.java:313)
      at oracle.security.jps.ee.util.JpsPlatformUtil.runJaasMode(JpsPlatformUtil.java:413)
      at oracle.security.jps.ee.http.JpsAbsFilter.runJaasMode(JpsAbsFilter.java:94)
      at oracle.security.jps.ee.http.JpsAbsFilter.doFilter(JpsAbsFilter.java:161)
      at oracle.security.jps.ee.http.JpsFilter.doFilter(JpsFilter.java:71)
      at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
      at oracle.dms.servlet.DMSServletFilter.doFilter(DMSServletFilter.java:136)
      at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
      at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3715)
      at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3681)
      at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
      at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
      at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2277)
      at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2183)
      at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1454)
      at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209)
      at weblogic.work.ExecuteThread.run(ExecuteThread.java:178)
  
  
  Caused by: org.springframework.ldap.AuthenticationException: [LDAP: error code 49 - 8009030C: LdapErr: DSID-0C0903AA, comment: AcceptSecurityContext error, data 2030, v1772
  
  at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:182)
      at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:266)
      at org.springframework.ldap.core.support.AbstractContextSource.getContext(AbstractContextSource.java:106)
      at org.springframework.ldap.core.support.AbstractContextSource.getReadOnlyContext(AbstractContextSource.java:125)
      at org.springframework.ldap.core.LdapTemplate.executeReadOnly(LdapTemplate.java:792)
      at org.springframework.security.ldap.SpringSecurityLdapTemplate.searchForSingleEntry(SpringSecurityLdapTemplate.java:196)
      at org.springframework.security.ldap.search.FilterBasedLdapUserSearch.searchForUser(FilterBasedLdapUserSearch.java:116)
      at org.springframework.security.ldap.authentication.BindAuthenticator.authenticate(BindAuthenticator.java:90)
      at org.springframework.security.ldap.authentication.LdapAuthenticationProvider.doAuthentication(LdapAuthenticationProvider.java:178)
      ... 34 more
  
  Caused by: javax.naming.AuthenticationException: [LDAP: error code 49 - 8009030C: LdapErr: DSID-0C0903AA, comment: AcceptSecurityContext error, data 2030, v1772
  at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3041)
      at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2987)
      at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2789)
      at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2703)
      at com.sun.jndi.ldap.LdapCtx.&lt;init&gt;(LdapCtx.java:293)
      at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:175)
      at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:193)
      at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:136)
      at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:66)
      at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667)
      at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
      at javax.naming.InitialContext.init(InitialContext.java:223)
      at javax.naming.ldap.InitialLdapContext.&lt;init&gt;(InitialLdapContext.java:134)
      at org.springframework.ldap.core.support.LdapContextSource.getDirContextInstance(LdapContextSource.java:43)
      at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:254)
      ... 41 more
  </code></pre>
  
  <p>I did a lookup and found Error code 2030 means that the DN of the user is invalid.</p>
  
  <p>Thanks in anticipation.</p>