8

I was wondering what I am doing wrong here to authenticate a user. I have an application where the user goes through several steps to activate their account, and upon doing so I would like to bypass the login form and take them directly to their dashboard.

Here is what my automated login function looks like:

protected void automatedLogin(String username, String password, HttpServletRequest request) {

        try {
            // Must be called from request filtered by Spring Security, otherwise SecurityContextHolder is not updated
            CustomUserDetailsService udService = new CustomUserDetailsService(userDAO, request);
            UserDetails uDetails = udService.loadUserByUsername(username);
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(uDetails, password);
            token.setDetails(new WebAuthenticationDetails(request));
            DaoAuthenticationProvider authenticator = new DaoAuthenticationProvider();
            Authentication authentication = authenticator.authenticate(token);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        } catch (Exception e) {
            e.printStackTrace();
            SecurityContextHolder.getContext().setAuthentication(null);
        }

    }

I must use the DaoAuthenticationProvider class as my authentication provider. I have verified that I am getting a UserDetails model containing the correct credentials, ID, authority roles, etc.

When it calls the authenticate method I run into a Null Pointer somewhere along the way in the DaoAuthenticationProvider class:

org.springframework.security.authentication.AuthenticationServiceException at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:109) at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:132) at com.bosch.actions.BaseController.doAutoLogin(BaseController.java:659) . . . Caused by: java.lang.NullPointerException at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:101)

I'm really not sure what is null, as I don't have the source code available.

Edit I was able to find the source code here - https://github.com/SpringSource/spring-security/blob/master/core/src/main/java/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java

I was able to get around the Null Pointer by explicitly setting the UserDetailsService on the object:

authenticator.setUserDetailsService(udService);

But now I get bad credentials exception when I know the password provided is correct, because I've seen it in the debugger in the UserDetails object set earlier in the code.

org.springframework.security.authentication.BadCredentialsException: Bad credentials at org.springframework.security.authentication.dao.DaoAuthenticationProvider.additionalAuthenticationChecks(DaoAuthenticationProvider.java:87) at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:149)

rawkfist0215
  • 1,445
  • 6
  • 21
  • 34
  • Spring Security is open source, you do have the source code available. You are probably having problems because DaoAuthenticationProvider is designed to be a spring managed bean. – samlewis Aug 01 '13 at 23:34

1 Answers1

10

I was able to get the authentication working by piecing together all of the properties defined in the spring bean definition and setting them programmatically on the DaoAuthenticationProvider object. Looking back this seems like it may have been a silly question, but I hope it helps someone!

Corrected Code:

protected void automatedLogin(String username, String password, HttpServletRequest request) {

        try {
            // Must be called from request filtered by Spring Security, otherwise SecurityContextHolder is not updated
            CustomUserDetailsService udService = new CustomUserDetailsService(userDAO, request);
            CustomMd5PasswordEncoder passEncoder = new CustomMd5PasswordEncoder();
            ReflectionSaltSource saltSource = new ReflectionSaltSource();
            saltSource.setUserPropertyToUse("salt");
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
            token.setDetails(new WebAuthenticationDetails(request));
            DaoAuthenticationProvider authenticator = new DaoAuthenticationProvider();
            authenticator.setUserDetailsService(udService);
            authenticator.setPasswordEncoder(passEncoder);
            authenticator.setSaltSource(saltSource);
            Authentication authentication = authenticator.authenticate(token);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        } catch (Exception e) {
            e.printStackTrace();
            SecurityContextHolder.getContext().setAuthentication(null);
        }

    }
rawkfist0215
  • 1,445
  • 6
  • 21
  • 34
  • 3
    Glad you found a fix, but to be honest, this is not how Spring Security was meant to be used. You're doing a lot of work on your own, that you should not have to. – Akshay Aug 02 '13 at 14:01
  • This is not the normal usage of Spring Security in the app. This is a one-time instance where I need to log the user in without them supplying the credentials in a form. Every other time they will be logging in via the form, and the spring security bean will be doing the work. Having explained that, if you are the one who downvoted the answer I hope you change your mind, because I think it unfairly hurts my reputation on StackOverflow. – rawkfist0215 Aug 02 '13 at 14:24
  • Rest assured my friend, I didn't down vote you. I don't think the answer was incorrect, I was just suggesting Spring Security wasn't meant to be used this way. And P.S. Down voting you would reduce my reputation on SO too... :) – Akshay Aug 02 '13 at 15:16
  • 7
    Additionally, authenticating programmatically in this way would also be of use inside a functional test suite, which is the reason I came here. Don't assume context. – Aquarelle Feb 08 '14 at 08:34