JwtFilter.java
package com.stocks.stockease.security;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.jspecify.annotations.NonNull;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
/**
* JWT token extraction and validation filter that runs once per request.
* Validates the Authorization header token, loads user details, and populates the SecurityContext.
*/
@Component
@org.springframework.context.annotation.Profile("!docs")
public class JwtFilter extends OncePerRequestFilter {
private static final Logger log = LoggerFactory.getLogger(JwtFilter.class);
private final JwtUtil jwtUtil;
private final UserDetailsService userDetailsService;
/**
* Constructs the filter with JWT utility and user details service dependencies.
*
* @param jwtUtil JWT operations utility
* @param userDetailsService loads user details for authentication
*/
public JwtFilter(JwtUtil jwtUtil, UserDetailsService userDetailsService) {
this.jwtUtil = jwtUtil;
this.userDetailsService = userDetailsService;
}
/**
* Validates the Bearer token from the Authorization header and populates the SecurityContext.
*
* @param request HTTP request with optional Authorization header
* @param response HTTP response
* @param filterChain next filter in chain
* @throws java.io.IOException if an I/O error occurs
* @throws jakarta.servlet.ServletException if a servlet error occurs
*/
@Override
protected void doFilterInternal(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain
) throws java.io.IOException, jakarta.servlet.ServletException {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String token = authHeader.substring(7);
if (jwtUtil.validateToken(token)) {
String username = jwtUtil.extractUsername(token);
var userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authToken);
} else {
log.debug("JWT validation failed for token");
}
}
filterChain.doFilter(request, response);
}
}