springspring-bootauthenticationjwt

What is the correct way to obtain an instance of the authenticated user if I'm using a JWT


I want to do so it's not necessary to pass the id or username in the request. I was doing it like this:

// In the controller
@DeleteMapping
public ResponseEntity<?> deleteStudent(@RequestHeader(name = "Authorization") String authHeader) {
    studentService.deleteEstudiante(authHeader); // Pass the token into the service
    return ResponseEntity.noContent().build();
}
// In the service
public void deleteStudent(String authHeader) {
    String token = jwtService.getTokenFromAuthorizationHeader(authHeader).orElseThrow(
            () -> new IllegalArgumentException("Invalid token")
    );

    String email = jwtService.getUsernameFromToken(token); // Get the subject
    
    // Rest of the logic where I search the user by email in the repository and I delete it
}

But I figured that's wrong. Which is the correct way?


Solution

  • I can't say which approach is right, as I think this depends on individual preferences or requirements.

    In my case, I use a JWT filter as shown below:

        @Override
        protected void doFilterInternal(
                HttpServletRequest request,
                HttpServletResponse response,
                FilterChain filterChain
        ) throws ServletException, IOException {
            String token = tokenParser.resolveToken(request);
    
            if (token != null && !token.isBlank()) {
                if (blackListRepository.existsByAccessToken(token)) {
                    throw new TokenExpiredException();
                }
    
                Authentication authentication = tokenParser.authentication(token);
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
    
            filterChain.doFilter(request, response);
        }
    

    Using this code, I register the following filter and execute it on a page that can only be accessed by logged-in users. The filter verifies the token and registers the current user in Spring Security's SecurityContextHolder.

    And then, I use the following method:

       public User getUser() {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            AuthDetails authDetails = null;
            if (authentication.getPrincipal() instanceof AuthDetails) {
                authDetails = (AuthDetails) authentication.getPrincipal();
            }
            if (authDetails == null || authDetails.getPhone() == null) {
                throw new BasicException(ErrorCode.TOKEN_NOT_VALID);
            }
    
            return userRepository.findByPhone(authDetails.getPhone()).orElseThrow(UserNotFoundException::new);
        }
    

    I retrieve the user from the SecurityContextHolder and use it.