title: LDAP Authentication with Spring Security 3
body: <p>I'm trying to secure parts of my Spring 3 MVC web application by authenticating against my organization's LDAP server. I'm new to LDAP so I'm learning as I go. I've been following the documentation <a href="http://static.springsource.org/spring-security/site/docs/3.1.x/reference/ldap.html" rel="nofollow">here</a> and the example <a href="https://github.com/SpringSource/spring-security/blob/9b423a7726e999b6c80e8c4a769a99dd634f56ce/samples/ldap/src/main/webapp/WEB-INF/applicationContext-security.xml" rel="nofollow">here</a> but I can't seem to get it right.</p>
  
  <p>Here is my security-context.xml</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &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/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
          http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"&gt;
  
      &lt;!-- Security Configuration --&gt;
      &lt;s:http&gt;
          &lt;s:intercept-url pattern="/page/tosecure/*" access="ROLE_USER" /&gt;
          &lt;s:http-basic /&gt;
      &lt;/s:http&gt;
  
      &lt;s:ldap-server root="dc=ldap,dc=sub,dc=myorg,dc=org" url="ldap.sub.myorg.org" port="636" /&gt;
  
      &lt;s:authentication-manager&gt;
          &lt;s:ldap-authentication-provider user-dn-pattern="uid={0},cn=users" /&gt;
          &lt;s:authentication-provider ref="ldapAuthProvider" /&gt;
      &lt;/s:authentication-manager&gt;
  
      &lt;bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource"&gt;
          &lt;constructor-arg value="ldaps://ldap.sub.myorg.org:636/dc=ldap,dc=sub,dc=myorg,dc=org" /&gt;
      &lt;/bean&gt;
  
      &lt;bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider"&gt;
          &lt;constructor-arg&gt;
              &lt;bean class="org.springframework.security.ldap.authentication.BindAuthenticator"&gt;
                  &lt;constructor-arg ref="contextSource" /&gt;
                  &lt;property name="userDnPatterns"&gt;
                      &lt;list&gt;
                          &lt;value&gt;uid={0},cn=users&lt;/value&gt;
                      &lt;/list&gt;
                  &lt;/property&gt;
              &lt;/bean&gt;
          &lt;/constructor-arg&gt;
          &lt;constructor-arg&gt;
              &lt;bean class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator"&gt;
                  &lt;constructor-arg ref="contextSource" /&gt;
                  &lt;constructor-arg value="cn=groups" /&gt;
                  &lt;property name="groupRoleAttribute" value="cn" /&gt;
              &lt;/bean&gt;
          &lt;/constructor-arg&gt;
      &lt;/bean&gt;
  
  &lt;/beans&gt;
  </code></pre>
  
  <p>And here is the error I am getting (the last few causes listed in the stack trace)</p>
  
  <pre><code>Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.securityContextSource': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.security.ldap.DefaultSpringSecurityContextSource]: Constructor threw exception; nested exception is org.springframework.ldap.BadLdapGrammarException: Failed to parse DN; nested exception is org.springframework.ldap.core.TokenMgrError: Lexical error at line 1, column 5.  Encountered: "." (46), after : ""
      at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:288)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1035)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:939)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
      at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
      at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
      at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
      at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
      at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:323)
      ... 106 more
  Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.security.ldap.DefaultSpringSecurityContextSource]: Constructor threw exception; nested exception is org.springframework.ldap.BadLdapGrammarException: Failed to parse DN; nested exception is org.springframework.ldap.core.TokenMgrError: Lexical error at line 1, column 5.  Encountered: "." (46), after : ""
      at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:162)
      at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:121)
      at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:280)
      ... 115 more
  Caused by: org.springframework.ldap.BadLdapGrammarException: Failed to parse DN; nested exception is org.springframework.ldap.core.TokenMgrError: Lexical error at line 1, column 5.  Encountered: "." (46), after : ""
      at org.springframework.ldap.core.DistinguishedName.parse(DistinguishedName.java:224)
      at org.springframework.ldap.core.DistinguishedName.&lt;init&gt;(DistinguishedName.java:174)
      at org.springframework.ldap.core.support.AbstractContextSource.setBase(AbstractContextSource.java:207)
      at org.springframework.security.ldap.DefaultSpringSecurityContextSource.&lt;init&gt;(DefaultSpringSecurityContextSource.java:67)
      at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
      at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
      at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
      at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
      at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:147)
      ... 117 more
  Caused by: org.springframework.ldap.core.TokenMgrError: Lexical error at line 1, column 5.  Encountered: "." (46), after : ""
      at org.springframework.ldap.core.DnParserImplTokenManager.getNextToken(DnParserImplTokenManager.java:678)
      at org.springframework.ldap.core.DnParserImpl.jj_consume_token(DnParserImpl.java:231)
      at org.springframework.ldap.core.DnParserImpl.SpacedEquals(DnParserImpl.java:114)
      at org.springframework.ldap.core.DnParserImpl.attributeTypeAndValue(DnParserImpl.java:94)
      at org.springframework.ldap.core.DnParserImpl.rdn(DnParserImpl.java:58)
      at org.springframework.ldap.core.DnParserImpl.dn(DnParserImpl.java:23)
      at org.springframework.ldap.core.DistinguishedName.parse(DistinguishedName.java:218)
  </code></pre>
  
  <p>It appears that it doesn't like the URL that is listed in the the constructor-arg for the contextSource bean although I'm not sure why.</p>
  
  <p>Also, I have a suspicion that other parts of this configuration are incorrect. For instance, I have the ldap server URL defined in the ldap-server tag and in the contextSource bean. That seems like unneeded duplication but it's how it is done in the examples. Could someone take a good look at the configuration to make sure it is sane?</p>
  
  <p>In addition, in case it's necessary, I'll talk a little about our LDAP server layout since it seems to be a little non-standard. A user's DN is constructed by uid={the_user_name},cn=users,dc=ldap,dc=sub,dc=myorg,dc=org. Group DNs are cn={group_name},cn=groups,dc=ldap,dc=sub,dc=myorg,dc=org and the members of a group are defined by a memberUid attribute. I say this is non-standard because, from what I've read, groups should be defined by an ou instead. But hopefully spring security can handle this setup. Does this configuration properly fetch the roles (groups) a user belongs to?</p>