Search code examples
javaauthenticationspring-mvcspring-security

How to manually set an authenticated user in Spring Security / SpringMVC


After a new user submits a 'New account' form, I want to manually log that user in so they don't have to login on the subsequent page.

The normal form login page going through the spring security interceptor works just fine.

In the new-account-form controller I am creating a UsernamePasswordAuthenticationToken and setting it in the SecurityContext manually:

SecurityContextHolder.getContext().setAuthentication(authentication);

On that same page I later check that the user is logged in with:

SecurityContextHolder.getContext().getAuthentication().getAuthorities();

This returns the authorities I set earlier in the authentication. All is well.

But when this same code is called on the very next page I load, the authentication token is just UserAnonymous.

I'm not clear why it did not keep the authentication I set on the previous request. Any thoughts?

  • Could it have to do with session ID's not being set up correctly?
  • Is there something that is possibly overwriting my authentication somehow?
  • Perhaps I just need another step to save the authentication?
  • Or is there something I need to do to declare the authentication across the whole session rather than a single request somehow?

Just looking for some thoughts that might help me see what's happening here.


Solution

  • I had the same problem as you a while back. I can't remember the details but the following code got things working for me. This code is used within a Spring Webflow flow, hence the RequestContext and ExternalContext classes. But the part that is most relevant to you is the doAutoLogin method.

    public String registerUser(UserRegistrationFormBean userRegistrationFormBean,
                               RequestContext requestContext,
                               ExternalContext externalContext) {
    
        try {
            Locale userLocale = requestContext.getExternalContext().getLocale();
            this.userService.createNewUser(userRegistrationFormBean, userLocale, Constants.SYSTEM_USER_ID);
            String emailAddress = userRegistrationFormBean.getChooseEmailAddressFormBean().getEmailAddress();
            String password = userRegistrationFormBean.getChoosePasswordFormBean().getPassword();
            doAutoLogin(emailAddress, password, (HttpServletRequest) externalContext.getNativeRequest());
            return "success";
    
        } catch (EmailAddressNotUniqueException e) {
            MessageResolver messageResolvable 
                    = new MessageBuilder().error()
                                          .source(UserRegistrationFormBean.PROPERTYNAME_EMAIL_ADDRESS)
                                          .code("userRegistration.emailAddress.not.unique")
                                          .build();
            requestContext.getMessageContext().addMessage(messageResolvable);
            return "error";
        }
    
    }
    
    
    private void doAutoLogin(String username, String password, HttpServletRequest request) {
    
        try {
            // Must be called from request filtered by Spring Security, otherwise SecurityContextHolder is not updated
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
            token.setDetails(new WebAuthenticationDetails(request));
            Authentication authentication = this.authenticationProvider.authenticate(token);
            logger.debug("Logging in with [{}]", authentication.getPrincipal());
            SecurityContextHolder.getContext().setAuthentication(authentication);
        } catch (Exception e) {
            SecurityContextHolder.getContext().setAuthentication(null);
            logger.error("Failure in autoLogin", e);
        }
    
    }