javaspringspring-securityspring-security-ldapspring-security-rest

nullpointer exception in createSuccessfulAuthentication with Ldap Authentication


I am new to spring security authentication. I am using AbstractUserDetailsAuthenticationProvider for my authentication

But I am getting below exception

java.lang.NullPointerException: null
    at org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.createSucccessfulAuthentication(AbstractLdapAuthenticationProvider.java:117)
    at org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:92)
    at com.example.securitydemo.security.CustomUserDetailsAuthenticationProvider.authenticate(CustomUserDetailsAuthenticationProvider.java:36)

Below is my CustomUserDetailsAuthenticationProvider.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider;
import org.springframework.security.ldap.userdetails.LdapUserDetailsImpl;
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;

public class CustomUserDetailsAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

    private ActiveDirectoryLdapAuthenticationProvider adAuthprovider;

    private UserDetailsContextMapper userDetailsContextMapper;

    @Autowired
    private AppGrantedAuthoritiesMapper mapper;

    public CustomUserDetailsAuthenticationProvider() {
    }

    public CustomUserDetailsAuthenticationProvider(ActiveDirectoryLdapAuthenticationProvider adAuthprovider) {
        this.adAuthprovider = adAuthprovider;
        if (this.adAuthprovider == null) {
            userDetailsContextMapper = new AppUserDetailsMapper();
            this.adAuthprovider.setUserDetailsContextMapper(userDetailsContextMapper);
        }
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        adAuthprovider.setAuthoritiesMapper(mapper);
        Authentication auth = adAuthprovider.authenticate(authentication);
        return auth;
    }

    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails,
            UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {

    }

    @Override
    protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {
        LdapUserDetailsImpl ud = (LdapUserDetailsImpl) authentication.getPrincipal();
        return ud;
    }

}

Below is my ReferAuthenticationSuccessHandler.java

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.Authentication;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

public class ReferAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws IOException, ServletException {
        handle(request, response, authentication);
    }

    protected void handle(final HttpServletRequest request, final HttpServletResponse response,
            final Authentication authentication) throws IOException {
        final String targetUrl = "home.html";
        redirectStrategy.sendRedirect(request, response, targetUrl);
    }

}

Below is my SecurityConfig.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

@Configuration
@EnableWebSecurity
@ComponentScan("com.example.securitydemo.security")
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(getAmsAuthProvider());
    }

    @Bean
    public AuthenticationSuccessHandler myAuthenticationSuccessHandler() {
        return new ReferAuthenticationSuccessHandler();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().disable().authorizeRequests().anyRequest().authenticated().and().formLogin()
                .successHandler(myAuthenticationSuccessHandler());

    }

    private CustomUserDetailsAuthenticationProvider getAmsAuthProvider() {

        ActiveDirectoryLdapAuthenticationProvider adLdap = new ActiveDirectoryLdapAuthenticationProvider("pac.***.com",
                "ldap://**.pac.com:389");
        adLdap.setSearchFilter("(&(objectClass=user)(sAMAccountName={1}");
        adLdap.setUseAuthenticationRequestCredentials(true);
        adLdap.setConvertSubErrorCodesToExceptions(true);
        CustomUserDetailsAuthenticationProvider authenticationProvider = new CustomUserDetailsAuthenticationProvider(
                adLdap);
        return authenticationProvider;
    }

}

Not sure what I am missing here, please help me to get resolve this issue


Solution

  • Make sure the user has authorities. Here is the source code of the AbstractLdapAuthenticationProvider https://github.com/spring-projects/spring-security/blob/master/ldap/src/main/java/org/springframework/security/ldap/authentication/AbstractLdapAuthenticationProvider.java

    Take a look at line 117 which your Stacktrace says. I would suggest debugging the the specific line and check which variable is empty.