I'm developing a REST service with Spring security, the backend generates the JWT without any problems, I checked all parts of the code, everything seems ok, but when POSTMAN sends a GET request to an endpoint protected by authentication, despite the token is valid, it receives the STATUS CODE: 403 (forbidden).
I think the issue resides into the security configuration; but I am not receiving any log information useful for debugging...could anyone suggest a solution?
.... the code
WebSecurityConfiguration
@Configuration@EnableWebSecurity@EnableMethodSecurity(prePostEnabled = false, securedEnabled = true)public class WebSecurityConfiguration{ private final JwtRequestFilter jwtRequestFilter; public WebSecurityConfiguration(JwtRequestFilter jwtRequestFilter) { this.jwtRequestFilter = jwtRequestFilter; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity security) throws Exception { return security .csrf(csrf -> csrf.disable()) .authorizeHttpRequests(requests -> requests.requestMatchers("/signup", "/login", "/hola").permitAll()) .authorizeHttpRequests(requests -> requests.requestMatchers("/api/**").authenticated()) .sessionManagement(management -> management.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class) .build(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception { return configuration.getAuthenticationManager(); }}
SimpleCorsFilter
@Component@Order(Ordered.HIGHEST_PRECEDENCE)public class SimpleCorsFilter implements Filter, WebMvcConfigurer { @Value("${app.client.url}") private String clientAppUrl = ""; public SimpleCorsFilter() {} @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; HttpServletRequest request = (HttpServletRequest) req; Map<String, String> map = new HashMap<>(); String originHeader = request.getHeader("origin"); response.setHeader("Access-Control-Allow-Origin", originHeader); response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE"); response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, observe"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "*"); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Expose-Headers", "Authorization"); response.addHeader("Access-Control-Expose-Headers", "responseType"); response.addHeader("Access-Control-Expose-Headers", "observe"); if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); } else { chain.doFilter(req, res); } } @Override public void init(FilterConfig filterConfig) { } @Override public void destroy() { }}
Login controller (this class generates the JWT)
@RestController@RequestMapping("/login")public class LoginContoller { private final AuthenticationManager authenticationManager; private final CustomerServiceImpl customerService; private final JwtUtil jwtUtil; public LoginContoller(AuthenticationManager authenticationManager, CustomerServiceImpl customerService, JwtUtil jwtUtil) { this.authenticationManager = authenticationManager; this.customerService = customerService; this.jwtUtil = jwtUtil; } @PostMapping public LoginResponse login(@RequestBody LoginRequest loginRequest, HttpServletResponse response) throws IOException { try { authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getEmail(), loginRequest.getPassword())); } catch (BadCredentialsException e) { throw new BadCredentialsException("Incorrect email or password."); } catch (DisabledException disabledException) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "Customer is not activated"); return null; } final UserDetails userDetails = customerService.loadUserByUsername(loginRequest.getEmail()); final String jwt = jwtUtil.generateToken(userDetails.getUsername()); return new LoginResponse(jwt); }}
HelloController (Here there is the endpoint who needs authentication)
@RestController@RequestMapping("/api")public class HelloController { @GetMapping("/hello") @ResponseBody public String hello(){ return("Hello from Authorized API request."); }}
It seems allright, but it doesn't work, any suggestion?