Configure Spring security for Ldap connection

16,490

In AbstractContextSource (parent of LdapContextSource), the Javadoc for the setBase() method says the following: "Set the base suffix from which all operations should origin. If a base suffix is set, you will not have to (and, indeed, must not) specify the full distinguished names in any operations performed.". Since you specify the full DN for the userDN/filter, hence you must not specify the base.

Try setting the userSearchBase either to an empty String (""), or remove the call all togehter.

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception{
     auth.ldapAuthentication()
         .contextSource()
         .url("ldaps://vldp.floal:636/DC=fg,DC=local")
         .managerDn("CN=A0XXX32,CN=Administration,CN=fdam,DC=fg,DC=local")
         .managerPassword(password)
         .and()         
         .userSearchBase("")     
         .userSearchFilter("CN={0},CN=ProxyUsers,CN=fdam,DC=fg,DC=local")
         .ldapAuthoritiesPopulator(myAuthPopulator);     
}
Share:
16,490

Related videos on Youtube

luca
Author by

luca

Updated on September 15, 2022

Comments

  • luca
    luca over 1 year

    I have to configure Spring security to authenticate user through LDAP. This is the subtree where manager user is:

    ldaps://vldp.floal:636/CN=Administration,CN=fdam,DC=fg,DC=local
    

    and this is where users are:

    ldaps://vldp.floal:636/CN=ProxyUsers,CN=fdam,DC=fg,DC=local
    

    So I use this setting:

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception{
         auth.ldapAuthentication()
          .contextSource()
            .url("ldaps://vldp.floal:636/DC=fg,DC=local")
            .managerDn("CN=A0XXX32,CN=Administration,CN=fdam,DC=fg,DC=local")
            .managerPassword(password)
          .and()         
          .userSearchBase("CN=ProxyUsers,CN=fdam")     
          .userSearchFilter("(CN={0})")
          .ldapAuthoritiesPopulator(myAuthPopulator);     
    }
    

    The problem is exception thrown when I try to make login through user, i receive this error:

    2016-03-25 14:43:14 [http-nio-8086-exec-6] ERROR o.s.s.w.a.UsernamePasswordAuthenticationFilter - An internal error occurred while trying to authenticate the user.
    org.springframework.security.authentication.InternalAuthenticationServiceException: [LDAP: error code 32 - 0000208D: NameErr: DSID-031522C9, problem 2001 (NO_OBJECT), data 0, best match of:
        'CN=fdam,DC=fg,DC=local'
     ]; nested exception is javax.naming.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-031522C9, problem 2001 (NO_OBJECT), data 0, best match of:
        'CN=fdam,DC=fg,DC=local'
     ]; remaining name 'cn=F67XXX7A,cn=ProxyUsers,cn=fdam'
        at org.springframework.security.ldap.authentication.LdapAuthenticationProvider.doAuthentication(LdapAuthenticationProvider.java:207) ~[spring-security-ldap-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:82) ~[spring-security-ldap-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:167) ~[spring-security-core-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:192) ~[spring-security-core-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:93) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:120) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) [spring-web-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) [spring-web-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.26]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.26]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) [catalina.jar:8.0.26]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [catalina.jar:8.0.26]
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [catalina.jar:8.0.26]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) [catalina.jar:8.0.26]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [catalina.jar:8.0.26]
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) [catalina.jar:8.0.26]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [catalina.jar:8.0.26]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) [catalina.jar:8.0.26]
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) [tomcat-coyote.jar:8.0.26]
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673) [tomcat-coyote.jar:8.0.26]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1526) [tomcat-coyote.jar:8.0.26]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1482) [tomcat-coyote.jar:8.0.26]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_60]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_60]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:8.0.26]
        at java.lang.Thread.run(Thread.java:745) [na:1.8.0_60]
    Caused by: org.springframework.ldap.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-031522C9, problem 2001 (NO_OBJECT), data 0, best match of:
        'CN=fdam,DC=fg,DC=local'
     ]; nested exception is javax.naming.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-031522C9, problem 2001 (NO_OBJECT), data 0, best match of:
        'CN=fdam,DC=fg,DC=local'
     ]; remaining name 'cn=F67XXX7A,cn=ProxyUsers,cn=fdam'
        at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:183) ~[spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
        at org.springframework.security.ldap.authentication.BindAuthenticator.bindWithDn(BindAuthenticator.java:148) ~[spring-security-ldap-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.security.ldap.authentication.BindAuthenticator.authenticate(BindAuthenticator.java:95) ~[spring-security-ldap-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        at org.springframework.security.ldap.authentication.LdapAuthenticationProvider.doAuthentication(LdapAuthenticationProvider.java:189) ~[spring-security-ldap-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        ... 41 common frames omitted
    Caused by: javax.naming.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-031522C9, problem 2001 (NO_OBJECT), data 0, best match of:
        'CN=fdam,DC=fg,DC=local'
     ]
        at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3160) ~[na:1.8.0_60]
        at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:3081) ~[na:1.8.0_60]
        at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2888) ~[na:1.8.0_60]
        at com.sun.jndi.ldap.LdapCtx.c_getAttributes(LdapCtx.java:1329) ~[na:1.8.0_60]
        at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_getAttributes(ComponentDirContext.java:235) ~[na:1.8.0_60]
        at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.getAttributes(PartialCompositeDirContext.java:141) ~[na:1.8.0_60]
        at javax.naming.directory.InitialDirContext.getAttributes(InitialDirContext.java:152) ~[na:1.8.0_60]
        at org.springframework.security.ldap.authentication.BindAuthenticator.bindWithDn(BindAuthenticator.java:124) ~[spring-security-ldap-4.0.2.RELEASE.jar:4.0.2.RELEASE]
        ... 43 common frames omitted
    

    There is a problem with spring parameters because if I use java code to authenticate users it works. I can't figure out where is the problem, can you help me?

    I went in debug and this is the output before the error:

    2016-03-30 11:35:22 [http-nio-8086-exec-6] DEBUG o.s.security.web.FilterChainProxy - /login at position 6 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
    2016-03-30 11:35:22 [http-nio-8086-exec-6] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/login'; against '/login'
    2016-03-30 11:35:22 [http-nio-8086-exec-6] DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Request is to process authentication
    2016-03-30 11:35:22 [http-nio-8086-exec-6] DEBUG o.s.s.authentication.ProviderManager - Authentication attempt using org.springframework.security.ldap.authentication.LdapAuthenticationProvider
    2016-03-30 11:35:22 [http-nio-8086-exec-6] DEBUG o.s.s.l.a.LdapAuthenticationProvider - Processing authentication request for user: F67XXX7A
    2016-03-30 11:35:22 [http-nio-8086-exec-6] DEBUG o.s.s.l.s.FilterBasedLdapUserSearch - Searching for user 'F67XXX7A', with user search [ searchFilter: '(CN={0})', searchBase: 'CN=fdam', scope: subtree, searchTimeLimit: 0, derefLinkFlag: false ]
    2016-03-30 11:35:23 [http-nio-8086-exec-6] DEBUG o.s.l.c.s.AbstractContextSource - Got Ldap context on server 'ldaps://vldp.floal:636/dc=fg,dc=local'
    2016-03-30 11:35:23 [http-nio-8086-exec-6] DEBUG o.s.s.l.SpringSecurityLdapTemplate - Searching for entry under DN 'dc=fg,dc=local', base = 'cn=fdam', filter = '(CN={0})'
    2016-03-30 11:35:23 [http-nio-8086-exec-6] DEBUG o.s.s.l.SpringSecurityLdapTemplate - Found DN: CN=F67XX7A,CN=ProxyUsers,CN=fdam
    2016-03-30 11:35:23 [http-nio-8086-exec-6] DEBUG o.s.s.l.a.BindAuthenticator - Attempting to bind as cn=F67XX7A,cn=ProxyUsers,cn=fdam,dc=fg,dc=local
    2016-03-30 11:35:23 [http-nio-8086-exec-6] DEBUG o.s.s.l.DefaultSpringSecurityContextSource - Removing pooling flag for user cn=F67XX7A,cn=ProxyUsers,cn=fdam,dc=fg,dc=local
    2016-03-30 11:35:23 [http-nio-8086-exec-6] DEBUG o.s.l.c.s.AbstractContextSource - Got Ldap context on server 'ldaps://vldp.floal:636/dc=fg,dc=local'
    2016-03-30 11:35:23 [http-nio-8086-exec-6] DEBUG o.s.s.l.a.BindAuthenticator - Retrieving attributes...
    2016-03-30 11:35:23 [http-nio-8086-exec-6] ERROR o.s.s.w.a.UsernamePasswordAuthenticationFilter - An internal error occurred while trying to authenticate the user.
    

    PS: If with a ldap browser use CN=F67XXX7A,CN=ProxyUsers,CN=fdam,DC=fg,DC=local it binds.

    UPDATE: if I use java without Spring login works, I need to use Spring and figure out how to configure it:

    @Override
    public void isAuthenticated(String username, String password) throws LdapException{
        if (databaseMatlabClientServices.getByUsersEnabled(username)== null)
            throw new LdapException("User doesn't exist into DART database. Please contact the administrator!");
        String dn="";;
        //First query to retriev DN
        Hashtable<String, Object> ldapEnv = new Hashtable<String, Object>();
        ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        ldapEnv.put(Context.PROVIDER_URL, env.getRequiredProperty(PROPERTY_NAME_LDAP_URL));
    //Without authentication        ldapEnv.put(Context.SECURITY_AUTHENTICATION, "none");
        //With authentication to access to LDAP server
        ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
        ldapEnv.put(Context.SECURITY_PRINCIPAL, env.getRequiredProperty(PROPERTY_NAME_LDAP_NAME));
        ldapEnv.put(Context.SECURITY_CREDENTIALS, env.getRequiredProperty(PROPERTY_NAME_LDAP_PASSWORD));
        String[] returnAttribute = {"dn"};
        DirContext ctx = null;
        NamingEnumeration<SearchResult> results = null;
        try {
            ctx = new InitialDirContext(ldapEnv);
            SearchControls controls = new SearchControls();
            controls.setReturningAttributes(returnAttribute);
            controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    // without authentication on local server String filter = "uid=" + username ;
            String filter = "CN=" + username ;
            results = ctx.search(env.getRequiredProperty(PROPERTY_NAME_LDAP_USERSEARCHBASE), filter, controls);
            if (results.hasMore())
                dn = results.nextElement().getNameInNamespace();
            else 
                throw new LdapException("Wrong username. Please retry!");
        } catch (NamingException e) {
            throw new LdapException(e);
        } finally {
            try{
                if (results != null)
                    results.close();             
                if (ctx != null) 
                    ctx.close();
            }catch(Exception e){
                throw new LdapException(e);
            }
        }
    
        //Second query to try to access with obtained Dn and given password
        Hashtable<String, Object> authEnv = new Hashtable<String, Object>();
        authEnv.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
        authEnv.put(Context.PROVIDER_URL, env.getRequiredProperty(PROPERTY_NAME_LDAP_URL));
        authEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
        authEnv.put(Context.SECURITY_PRINCIPAL, dn);
        authEnv.put(Context.SECURITY_CREDENTIALS, password);
        DirContext ctx2 = null;
        try {
            ctx2 = new InitialDirContext(authEnv);
        } catch (AuthenticationException authEx) {
            throw new LdapException("Authentication error. Password was wrong");
        } catch(Exception e){
            throw new LdapException(e);
        }finally {
            try{         
                if (ctx2 != null) 
                    ctx2.close();
            }catch(Exception e){
                throw new LdapException(e);
            }
        }
    }
    

    UPDATE @pczeus code: To set referral=follow I have used this code:

    DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource("ldaps://vldp.floal:636/");
    contextSource.setUserDn("CN=A0XXX32,CN=Administration,CN=fdam,DC=fg,DC=local");
    contextSource.setPassword(password);
    contextSource.setReferral("follow"); 
    contextSource.afterPropertiesSet();
    
    LdapAuthenticationProviderConfigurer<AuthenticationManagerBuilder> ldapAuthenticationProviderConfigurer = auth.ldapAuthentication();
    
    ldapAuthenticationProviderConfigurer
        .ldapAuthoritiesPopulator(myAuthPopulator)
        .userSearchFilter("(CN={0},CN=ProxyUsers,CN=fdam,DC=fg,DC=local)")
        .userSearchBase("")
        .contextSource(contextSource);
    

    and I receive the classic exception:

    2016-04-07 09:34:41 [http-nio-8086-exec-4] ERROR o.s.s.w.a.UsernamePasswordAuthenticationFilter - An internal error occurred while trying to authenticate the user.
    org.springframework.security.authentication.InternalAuthenticationServiceException: [LDAP: error code 32 - 0000208D: NameErr: DSID-031001E5, problem 2001 (NO_OBJECT), data 0, best match of:
        ''
     ]; nested exception is javax.naming.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-031001E5, problem 2001 (NO_OBJECT), data 0, best match of:
        ''
     ]; remaining name '/'
    

    if I add .userSearchBase("CN=ProxyUsers,CN=fgadam,DC=fg,DC=local") I receive

    2016-04-07 10:32:56 [http-nio-8086-exec-4] DEBUG o.s.s.l.s.FilterBasedLdapUserSearch - Searching for user 'F6XXX7A', with user search [ searchFilter: '(CN={0},CN=ProxyUsers,CN=fdam,DC=fg,DC=local)', searchBase: 'CN=ProxyUsers,CN=fdam,DC=fg,DC=local', scope: subtree, searchTimeLimit: 0, derefLinkFlag: false ]
    2016-04-07 10:32:57 [http-nio-8086-exec-4] DEBUG o.s.l.c.s.AbstractContextSource - Got Ldap context on server 'ldaps://vldp.floal:636/'
    2016-04-07 10:32:57 [http-nio-8086-exec-4] DEBUG o.s.s.l.SpringSecurityLdapTemplate - Searching for entry under DN '', base = 'cn=ProxyUsers,cn=fdam,dc=fg,dc=local', filter = '(CN={0},CN=ProxyUsers,CN=fdam,DC=fg,DC=local)'
    2016-04-07 10:32:57 [http-nio-8086-exec-4] DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials
    

    where DN is '', why?

  • luca
    luca about 8 years
    Thanks for your reply, if I use userSearchBase("CN=ProxyUsers,CN=fdam,DC=fg,DC=local" I receive the same error, furthermore now I can't use my manager credential to login to my web portal because it isn't in ProxyUsers
  • pczeus
    pczeus about 8 years
    Did you try the contextSource.setReferral("follow") as suggested by @Maciej Czarnecki ?
  • luca
    luca about 8 years
    you can see the error with referral in UPDATE @pczeus code in my main post