I have implemented a spring boot project with JWT authentication. I want to have two endpoint which any body can access (“auth”,”images”), while protecting all the other endpoints. The problem is the server always return Forbidden status (403) instead of Unauthorized (401), when a client send a request without a valid token to a protected endpoint. Also beside status 403 the response won’t provide any message.
Here is my security filter chain:
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http.authorizeHttpRequests(requests -> requests
.requestMatchers("/auth/**").permitAll()
.requestMatchers("/images/**").permitAll()
.anyRequest().authenticated())
.csrf(csrf -> csrf.disable())
.sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilterBefore(authorizeFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
And here is the authorize filter:
@Component
public class AuthorizeFilter extends OncePerRequestFilter {
@Autowired
private CustomUserDetailService userDetailService;
@Autowired
private JWTUtil jwt;
@Override
protected void doFilterInternal(@SuppressWarnings("null") HttpServletRequest request,
@SuppressWarnings("null") HttpServletResponse response, @SuppressWarnings("null") FilterChain filterChain)
throws ServletException, IOException {
try {
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7);
String username = jwt.extractUsername(token);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails user = userDetailService.loadUserByUsername(username);
if (username.equals(user.getUsername())) {
UsernamePasswordAuthenticationToken authenticate = new UsernamePasswordAuthenticationToken(user,
null, user.getAuthorities());
authenticate.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticate);
}
}
}
filterChain.doFilter(request, response);
} catch (Exception e) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
}
}
Here is the postman result without token: image
The filter only works when I adding :
.requestMatchers("/**").permitAll()
But It let reach any unauthorized user to any protected endpoint. Is any body know why is this the case?
Thanks for any help in advance.