Nickname11
Nickname11

Reputation: 571

How to extend logged-in user informations in Spring Security?

I am using this tutorial as a base of my application. Now, I would like to extend current logged in user with additional information (user id and email address). The goal is to beeing able to perform this operation in controller: authentication.getId() or authentication.getPrincipal().getId()

In given tutorial i particularry don't understand few elements:

  1. What's the role of UserDetailsServiceImpl?
  2. What's going on with UsernamePasswordAuthenticationToken?

In one place it is used like this:

private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
        String token = request.getHeader(HEADER_STRING);
        if (token != null) {
            // parse the token.
            String user = JWT.require(Algorithm.HMAC512(SECRET.getBytes()))
                    .build()
                    .verify(token.replace(TOKEN_PREFIX, ""))
                    .getSubject();

            if (user != null) {
                return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
            }
            return null;
        }
        return null;
    }

While in other in this way:

return authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            creds.getUsername(),
                            creds.getPassword(),
                            new ArrayList<>())

Do I have to extend User class, or somehow UsernamePasswordAuthenticationToken? Looking forward for your answers!

Upvotes: 0

Views: 697

Answers (1)

Set a principal you want to Authentication:

public class JWTAuthorizationFilter extends BasicAuthenticationFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest req,
                                    HttpServletResponse res,
                                    FilterChain chain) throws IOException, ServletException {
        ...
        String username = getUsername(req);
        ApplicationUser applicationUser = applicationUserRepository.findByUsername(username);
        Authentication authentication = new UsernamePasswordAuthenticationToken(applicationUser, null, new ArrayList<>());

        SecurityContextHolder.getContext().setAuthentication(authentication);
        chain.doFilter(req, res);
    }

(On above example, set logged-in ApplicationUser as a principal.)

And then, controllers can obtain principal by SecurityContext:

    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    ApplicationUser principal = (ApplicationUser) authentication.getPrincipal();
    System.out.println(principal.getId());

Here is complete diff.


What's the role of UserDetailsServiceImpl?

Here is UserDetailsService description:

UserDetailsService is a DAO interface for loading data that is specific to a user account. It has no other function other to load that data for use by other components within the framework. It is not responsible for authenticating the user. Authenticating a user with a username/password combination is most commonly performed by the DaoAuthenticationProvider, which is injected with a UserDetailsService to allow it to load the password (and other data) for a user in order to compare it with the submitted value.

 

What's going on with UsernamePasswordAuthenticationToken?

Commonly, used as DaoAuthenticationProvider#authenticate's argument(see also supports). On this tutorial, it is called by JWTAuthenticationFilter.

On the other hand, JWTAuthorizationFilter also uses UsernamePasswordAuthenticationToken, but this type is not required here(merely used as Authentication implementation).

Upvotes: 1

Related Questions