7

My application uses Spring Security, and my client requires:

  • users to be able to automatically login after signup.
  • an admin to login as any user without knowing their password.

So I need to figure out how to login as any user automatically without knowing their password.

How can this be accomplished using Spring Security?

Brad Parks
  • 66,836
  • 64
  • 257
  • 336

3 Answers3

7

To get this to work, I had to:

Configure a reference to the UserDetailsService (jdbcUserService)

<authentication-manager>
<authentication-provider>
<jdbc-user-service id="jdbcUserService" data-source-ref="dataSource"
  users-by-username-query="select username,password, enabled from users where username=?" 
  authorities-by-username-query="select u.username, ur.authority from users u, user_roles ur where u.user_id = ur.user_id and u.username =?  " 
/>
</authentication-provider>
</authentication-manager>

Autowire my userDetailsManager in my controller:

@Autowired
@Qualifier("jdbcUserService")  // <-- this references the bean id
public UserDetailsManager userDetailsManager;

In the same controller, authenticate my user like so:

@RequestMapping("/automatic/login/test")
public @ResponseBody String automaticLoginTest(HttpServletRequest request) 
{
    String username = "anyUserName@YourSite.com";

    Boolean result = authenticateUserAndInitializeSessionByUsername(username, userDetailsManager, request);

    return result.toString();
}

public boolean authenticateUserAndInitializeSessionByUsername(String username, UserDetailsManager userDetailsManager, HttpServletRequest request)
{
    boolean result = true;

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

        // Authenticate the user
        UserDetails user = userDetailsManager.loadUserByUsername(username);
        Authentication auth = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(auth);
    }
    catch (Exception e)
    {
      System.out.println(e.getMessage());

      result = false;
    }

    return result;
}

Note that a good precursor to just using spring security for your app can be found here.

Brad Parks
  • 66,836
  • 64
  • 257
  • 336
  • the Javadoc about UsernamePasswordAuthenticationToken said: _This constructor should only be used by AuthenticationManager or AuthenticationProvider implementations that are satisfied with producing a trusted (i.e. isAuthenticated() = true) authentication token._ – xedo Dec 17 '14 at 13:39
  • This was the only way I found to get "logging in as a user without knowing their password" to work... I'm not working on that project anymore, but think that the docs could be read as "this constructor should only be used by code that's satisfied with producing a trusted (i.e. isAuthenticated() = true) authentication token"... if you find a better way, definitely post it here! – Brad Parks Dec 17 '14 at 13:47
  • In my spring security integrated extjs application this only works for me after replacing the existing spring security context key in the session with the newly authenticated security context. `request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());` – G 1 Aug 27 '16 at 06:14
1

for second problem

an admin to login as any user without knowing their password.

you should use switch user feature from spring. javadoc and article

Jigar Parekh
  • 6,163
  • 7
  • 44
  • 64
1

This is answer to above question In Controller:

@RequestMapping(value = "/registerHere", method = RequestMethod.POST)
    public ModelAndView registerUser(@ModelAttribute("user") Users user, BindingResult result,
            HttpServletRequest request, HttpServletResponse response) {
        System.out.println("register 3");

        ModelAndView mv = new ModelAndView("/home");
        mv.addObject("homePagee", "true");

        String uname = user.getUsername();

        if (userDAO.getUserByName(uname) == null) {

            String passwordFromForm = user.getPassword();
            userDAO.saveOrUpdate(user);

            try {
                authenticateUserAndSetSession(user, passwordFromForm, request);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }


        }

        System.out.println("register 4");

        log.debug("Ending of the method registerUser");
        return mv;
    }

Further above method in controller is defined as:

`private void authenticateUserAndSetSession(Users user, String passwor`dFromForm, HttpServletRequest request){

        String username = user.getUsername();
        System.out.println("username:  " + username + " password: " + passwordFromForm);                        

        UserDetails userDetails = userDetailsService.loadUserByUsername(user.getUsername());

        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(username, passwordFromForm, userDetails.getAuthorities());
        request.getSession();

        System.out.println("Line Authentication 1");

        usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetails(request));

        System.out.println("Line Authentication 2");

        Authentication authenticatedUser = authenticationManager.authenticate(usernamePasswordAuthenticationToken);

        System.out.println("Line Authentication 3");


        if (usernamePasswordAuthenticationToken.isAuthenticated()) {
            SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
            System.out.println("Line Authentication 4");

        }

     request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());// creates context for that session.

        System.out.println("Line Authentication 5");

        session.setAttribute("username", user.getUsername());

        System.out.println("Line Authentication 6");

        session.setAttribute("authorities", usernamePasswordAuthenticationToken.getAuthorities());

        System.out.println("username:  " + user.getUsername() + "password: " + user.getPassword()+"authorities: "+ usernamePasswordAuthenticationToken.getAuthorities());

        user = userDAO.validate(user.getUsername(), user.getPassword());
        log.debug("You are successfully register");

    }

Other answers didnt suggest to put it in try/catch so one does not realize why logic is not working as code runs...and nothing is there neither error or exception on console. So if you wont put it in try catch you wont get exception of bad credentials.

Yogesh Devgun
  • 1,297
  • 1
  • 19
  • 36