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?
3 Answers
Answers 1
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); }
Answers 2
We have a legacy app that uses Spring Security 3.2.5. We still use XML to config it. Maybe my config could help you to identify whats going on with yours.
What I noticed is that your userSearchBase
does not use the complete "FQDN". Try using userSearchBase("CN=ProxyUsers,CN=fdam,DC=fg,DC=local")
(despite the log msg "Attempting to bind as cn=F67XX7A,cn=ProxyUsers,cn=fdam,dc=fg,dc=local").
Another hint is to use a LDAP browser tool in order navigate into the ldap server and check to see if the CN, DN and OU are ok.
<ldap-server url="ldap://SERVERNAME.XPTO.BLAH:389" manager-dn="usrLogin" manager-password="usrPwd" /> <authentication-manager> <ldap-authentication-provider role-prefix="" user-search base="OU=BR,OU=MYCOMP,DC=XPTO,DC=BLAH" user-search-filter="sAMAccountName={0}" group-search-base="OU=Groups,OU=BR,OU=MYCOMP,DC=XPTO,DC=BLAH" group-search-filter="member={0}" /> </authentication-manager> <beans:bean id="ldapEnv" class="java.util.Hashtable" scope="prototype"> <beans:constructor-arg> <beans:map key-type="java.lang.String" value-type="java.lang.String"> <beans:entry key="java.naming.factory.initial" value="com.sun.jndi.ldap.LdapCtxFactory" /> <beans:entry key="java.naming.provider.url" value="ldap://SERVERNAME.XPTO.BLAH:389" /> <beans:entry key="java.naming.security.authentication" value="simple" /> <beans:entry key="java.naming.security.principal" value="usrLogin" /> <beans:entry key="java.naming.security.credentials" value="usrPwd" /> </beans:map> </beans:constructor-arg> </beans:bean>
Answers 3
You can try below approach i.e use administrative user who has the necessary permissions
LDAP authentication without managerDN and manager password
Additional info: LDAP+Spring
0 comments:
Post a Comment