@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtService jwtService;
private final CustomUserDetailsService userDetailsService;
public JwtAuthenticationFilter(JwtService jwtService, CustomUserDetailsService userDetailsService) {
this.jwtService = jwtService;
this.userDetailsService = userDetailsService;
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String token = extractTokenFromHeader(request);
if (token != null && SecurityContextHolder.getContext().getAuthentication() == null) {
try {
// 1. Validate token signature + expiration
if (!jwtService.isTokenValid(token)) {
log.warn("JWT is invalid or expired");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid JWT token");
return;
}
// 2. Extract username
Optional<String> usernameOpt = jwtService.extractUsername(token);
if (usernameOpt.isEmpty()) {
log.warn("JWT does not contain username");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid JWT token");
return;
}
String username = usernameOpt.get();
// 3. Extract roles
List<String> roles = jwtService.extractClaim(token, claims -> {
Object rolesObj = claims.get("roles");
if (rolesObj instanceof List<?>) {
return ((List<?>) rolesObj).stream()
.filter(String.class::isInstance)
.map(String.class::cast)
.collect(Collectors.toList());
}
return Collections.emptyList();
});
List<SimpleGrantedAuthority> authorities = roles.stream()
.map(SimpleGrantedAuthority::new)
.toList();
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(username, null, authorities);
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
} catch (Exception e) {
log.error("Failed to authenticate JWT token: {}", e.getMessage());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid JWT token");
return;
}
}
filterChain.doFilter(request, response);
}
private String extractTokenFromHeader(HttpServletRequest request) {
String authHeader = request.getHeader("Authorization");
return (authHeader != null && authHeader.startsWith("Bearer "))
? authHeader.substring(7)
: null;
}
}