6

I have an application which uses spring-security. In my signup process, a new user entity gets persisted with the HASHED password, an email containing an activation token is the sent to the user. Clicking on this token directs the user to a UserActivationServlet which looks up the user by the token, activates the user and redirects them to the application. I would like to automatically log the user into the application and have included this method in my servlet to do this

    private void authenticateUserAndSetSession(HttpServletRequest request, User u) {
    UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
            u.getUsername(), u.getPassword()); //PROBLEM: THIS PASSWORD IS HASHED

    // generate session if one doesn't exist
    request.getSession();

    token.setDetails(new WebAuthenticationDetails(request));
    Authentication authenticatedUser = authenticationManager.authenticate(token);

    SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
    request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
            SecurityContextHolder.getContext());
}

The problem here is that that the password field on the User entity has been hashed when it was created. So the only other option I can think of is to pass the unhashed password as a request parameter to the servelet (nasty!)

Have I missed something, is there another way of pre-authenticating the user?

Thanks

Simeon
  • 7,582
  • 15
  • 64
  • 101
Clinton Bosch
  • 2,497
  • 4
  • 32
  • 46
  • 1
    I was being stupid here, the user has clicked on the activation link and we have looked him up so clearly we have a valid user, so there is no need to re-authenticate him with the authenticationManager and so no need to use credentials when creating the Token, just create it as follows: PreAuthenticatedAuthenticationToken token = new PreAuthenticatedAuthenticationToken( p, null, p.getAuthorities()); – Clinton Bosch Jul 06 '11 at 12:35
  • another similar question (and answer) can be found here: http://stackoverflow.com/a/12057327/26510 – Brad Parks Aug 22 '12 at 11:44
  • 1
    @ClintonBosch You can write the comment as an answer and accept it – fglez Mar 04 '13 at 09:43

2 Answers2

3

The user has clicked on the activation link and we have looked him up so clearly we have a valid user, so there is no need to re-authenticate him with the authenticationManager and so no need to use credentials when creating the Token, just create it as follows:

PreAuthenticatedAuthenticationToken token = new PreAuthenticatedAuthenticationToken( p, null, p.getAuthorities());
nhahtdh
  • 55,989
  • 15
  • 126
  • 162
Clinton Bosch
  • 2,497
  • 4
  • 32
  • 46
0

If I understand you correctly SOA can help you.

You don't need to make a redirect to the login page, but rather call the service that logs the user in. Any login related logic residing in a controller (or somewhere above the service layer) should be moved 'down' and used by your servlet.

The service could look something like:

public interface LoginService {
    // this will be called from the login page
    public void login(String username, String hashedPass);

    // this will only be visible to other services
    // you can secure it with AOP and Spring security's method security
    public void login(String username);
}

Then you can call loginService.login(username); from your servlet.

Or in your exact case pass your token without a password:

loginService.login(new UsernamePasswordAuthenticationToken(u.getUsername(), ""));
Simeon
  • 7,582
  • 15
  • 64
  • 101