29

I am trying to perform an automatic login when the user clicks a link in their email with Spring Security.

I have seen a lot of examples to perform a programmatic login like the following:

UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
try {
    Authentication auth = authenticationManager.authenticate(token);
    SecurityContextHolder.getContext().setAuthentication(auth);
    repository.saveContext(SecurityContextHolder.getContext(), request, response);
    rememberMeServices.loginSuccess(request, response, auth);
 ....

The problem I see is that I do not have the original password so I can't create a UsernamePasswordAuthenticationToken. Any other way to login the user if I do not have the plain text password (I have the one that is encoded)?

Thanks in advance.

Agustin Lopez
  • 1,355
  • 4
  • 18
  • 34

1 Answers1

66

Be careful that you know what you are doing in terms of allowing login from a link within an email. SMTP is not a secure protocol and so it is typically bad to rely on someone having an email as a form of authentication.

You do not need to use the AuthenticationManager if you already know they are authenticated. Instead you can just set the Authentication directly as shown below:

Authentication authentication = new UsernamePasswordAuthenticationToken(user, null,
    AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContextHolder.getContext().setAuthentication(authentication);

If you want a complete example, you can refer to the SignupController in the secure mail application that was the basis for Getting Started with Spring Security 3.1 (InfoQ video of presentation).

Rob Winch
  • 21,440
  • 2
  • 59
  • 76
  • Awesome answer. Thank you very much. I didn't know it was risky to do this but I will analyze which is the best approach in my case :). – Agustin Lopez Jul 03 '12 at 19:16
  • What would you suggest to implement authentication without passwords in Spring then? Or, is authentication without passwords not possible in Spring? – Utku Jan 15 '18 at 15:20
  • 3
    By the way, if authentication by a link sent via email is not secure, then nearly no web site is secure, since nearly all websites are using email for password reset links. Am I missing something here? – Utku Jan 15 '18 at 15:23
  • Doesn't this assign ROLE_USER, without loading the real roles from the DB? – Bobby Jun 26 '19 at 08:04
  • @Bobby ROLE_USER is spring default role I believe. – Motolola Jan 14 '20 at 17:55
  • 1
    I tried your code but SecurityUtils.getCurrentUserLogin(); still prints anonymous@localhost. What might be a reason for that? I removed password field from User – lightning mcqueen Sep 19 '20 at 17:35
  • Not working for me. getPrincipal is returning wrong Object. – Jef Jan 05 '21 at 06:38
  • I'd recommend using a service like ownid.com; check out their demo https://demo.ownid.com – Victor Navarro Jun 20 '22 at 09:56
  • 1
    This worked for me, it adds right roles and sets right user: `UserDetails userDetails = userDetailsService.loadUserByUsername("ivo") Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.authorities) SecurityContextHolder.getContext().setAuthentication(authentication)` – ivom Jun 21 '22 at 11:38