Uppa
Uppa

Reputation: 23

PartialResultException: Unprocessed Continuation Reference(s); remaining name ''

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

Answers (1)

Uppa
Uppa

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

Related Questions