Reputation: 23
We are currently updating our LDAP server. In previous server we used anonymous bind. These are the old properties that we used:
url = ldap://urlexample.com/dc=company,dc=com
filter = (uid={0})
base = ou=People,ou=Corporate
dn =
password =
These properties worked OK with the following spring security config class:
/*Omitted imports to simplify*/
@Configuration
@EnableWebSecurity(debug = false)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
@Value("${base}")
private String userSearchBase;
@Value("${filter}")
private String userSearchFilter;
@Value("${url}")
private String ldapUrl;
@Value("${dn}")
private String managerDn;
@Value("${password}")
private String managerPassword;
private String performLoginUrl = "/perform_login";
private String loginUrl = "/login";
private String userNameParam = "username";
private String passwordParam = "password";
@Autowired
private CustomLoginSuccessHandler customLoginSuccessHandler;
@Autowired
private CustomLoginFailureHandler customLoginFailureHandler;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.userSearchBase(userSearchBase)
.userSearchFilter(userSearchFilter)
.contextSource(contextSource());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
// Some other code...
// security:form-login
http.formLogin()
.loginPage(loginUrl)
.loginProcessingUrl(performLoginUrl)
.successHandler(customLoginSuccessHandler)
.failureHandler(customLoginFailureHandler)
.usernameParameter(userNameParam)
.passwordParameter(passwordParam)
.permitAll();
// some other code...
}
@Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
//some other code...
}
@Bean
public BaseLdapPathContextSource contextSource() {
DefaultSpringSecurityContextSource ctxSource = new DefaultSpringSecurityContextSource(ldapUrl);
if(StringUtils.isNotBlank(managerDn)) {
ctxSource.setUserDn(managerDn);
}
if(StringUtils.isNotBlank(managerPassword)) {
ctxSource.setPassword(managerPassword);
}
// ctxSource.setAnonymousReadOnly(Boolean.TRUE);
ctxSource.afterPropertiesSet();
return ctxSource;
}
@Bean(name = "ldapTemplate", autowire = Autowire.BY_NAME)
public LdapTemplate ldapTemplate() {
return new LdapTemplate(contextSource());
}
}
The new properties for the new LDAP are the following:
url = ldaps://urlexample2/dc=corp,dc=company,dc=com
filter = (&(sAMAccountName={0})(objectclass=user))
base = OU=CorpUsers
dn= CN=ldap,OU=ServiceAccounts,DC=corp,DC=company,DC=com
password = pwdExample
With this information, the same code now returns a PartialResultException during login process (I'm assuming that this is happening during login process because no logs from successHandler or failureHandler appear). The following exception appears after I introduce my credentials and click on "Login" form button:
org.springframework.ldap.PartialResultException: Unprocessed Continuation Reference(s); nested exception is javax.naming.PartialResultException: Unprocessed Continuation Reference(s); remaining name ''
org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:216)
org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:385)
org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:328)
org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:629)
org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:570)
org.springframework.security.ldap.SpringSecurityLdapTemplate.searchForMultipleAttributeValues(SpringSecurityLdapTemplate.java:241)
org.springframework.security.ldap.SpringSecurityLdapTemplate.searchForSingleAttributeValues(SpringSecurityLdapTemplate.java:166)
org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator.getGroupMembershipRoles(DefaultLdapAuthoritiesPopulator.java:241)
org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator.getGrantedAuthorities(DefaultLdapAuthoritiesPopulator.java:210)
org.springframework.security.ldap.authentication.LdapAuthenticationProvider.loadUserAuthorities(LdapAuthenticationProvider.java:213)
org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:89)
org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199)
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:124)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
root cause
javax.naming.PartialResultException: Unprocessed Continuation Reference(s); remaining name ''
com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2917)
com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2891)
com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1846)
com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1769)
com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search(ComponentDirContext.java:392)
com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:358)
com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:341)
javax.naming.directory.InitialDirContext.search(InitialDirContext.java:267)
org.springframework.ldap.core.LdapTemplate$4.executeSearch(LdapTemplate.java:322)
org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:363)
org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:328)
org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:629)
org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:570)
org.springframework.security.ldap.SpringSecurityLdapTemplate.searchForMultipleAttributeValues(SpringSecurityLdapTemplate.java:241)
org.springframework.security.ldap.SpringSecurityLdapTemplate.searchForSingleAttributeValues(SpringSecurityLdapTemplate.java:166)
org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator.getGroupMembershipRoles(DefaultLdapAuthoritiesPopulator.java:241)
org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator.getGrantedAuthorities(DefaultLdapAuthoritiesPopulator.java:210)
org.springframework.security.ldap.authentication.LdapAuthenticationProvider.loadUserAuthorities(LdapAuthenticationProvider.java:213)
org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:89)
org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199)
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:124)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
Could someone explain me why is this happening and how could I solve this? Not an expert about LDAP. If you need more info just tell me, I'll update the question.
Upvotes: 1
Views: 2976
Reputation: 23
I think I solved my problem. Apparently the LdapAuthoritiesPopulator
used in LdapAuthenticationProviderConfigurer
does not ignore partial results. So what I did was to define a DefaultAuthoritiesPopulator
that ignores partial results and pass it to my LdapAuthenticationProviderConfigurer
.
Here are the changes apllied:
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.ldapAuthoritiesPopulator(authoritiesPopulator())
.userSearchBase(userSearchBase)
.userSearchFilter(userSearchFilter)
.contextSource(contextSource());
}
public LdapAuthoritiesPopulator authoritiesPopulator() {
DefaultLdapAuthoritiesPopulator populator =
new DefaultLdapAuthoritiesPopulator(
contextSource(), userSearchBase);
populator.setGroupSearchFilter(userSearchFilter);
populator.setIgnorePartialResultException(true);
return populator;
}
Upvotes: 0