I had a problem with CORS, and I tried everything I could find on Stack Overflow, and basically everything I found on Google, and I had no luck.
So, I have user authentication on my server, and I have a login page in my interface. I connected the login page using Axios so that I could send a request and tried to log in, but I continued to receive errors such as "Pre-Professional Request", so I fixed it and then started to receive the message "Post 403 Forbidden".
It looked like this:
POST http://localhost:8080/api/v1/login/ 403 (Forbidden)
Even trying to log in using Postman does not work, so something is clearly wrong. The class file below will be published
On my backend, I have a class called WebSecurityConfig that applies to all CORS stuff:
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsServiceImpl userDetailsService; @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurerAdapter() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedMethods("GET", "POST", "HEAD", "PUT", "DELETE", "OPTIONS"); } }; } @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("*"); // TODO: lock down before deploying config.addAllowedHeader("*"); config.addExposedHeader(HttpHeaders.AUTHORIZATION); config.addAllowedMethod("*"); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } @Override protected void configure(HttpSecurity http) throws Exception { http.headers().frameOptions().disable(); http .cors() .and() .csrf().disable().authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/h2/**").permitAll() .antMatchers(HttpMethod.POST, "/api/v1/login").permitAll() .anyRequest().authenticated() .and() // We filter the api/login requests .addFilterBefore(new JWTLoginFilter("/api/v1/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class); // And filter other requests to check the presence of JWT in header //.addFilterBefore(new JWTAuthenticationFilter(), // UsernamePasswordAuthenticationFilter.class); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // Create a default account auth.userDetailsService(userDetailsService); // auth.inMemoryAuthentication() // .withUser("admin") // .password("password") // .roles("ADMIN"); } }
In our interface, written in VueJS and using Axios to invoke
<script> import { mapActions } from 'vuex'; import { required, username, minLength } from 'vuelidate/lib/validators'; export default { data() { return { form: { username: '', password: '' }, e1: true, response: '' } }, validations: { form: { username: { required }, password: { required } } }, methods: { ...mapActions({ setToken: 'setToken', setUser: 'setUser' }), login() { this.response = ''; let req = { "username": this.form.username, "password": this.form.password }; this.$http.post('/api/v1/login/', req) .then(response => { if (response.status === 200) { this.setToken(response.data.token); this.setUser(response.data.user); this.$router.push('/dashboard'); } else { this.response = response.data.error.message; } }, error => { console.log(error); this.response = 'Unable to connect to server.'; }); } } } </script>
Therefore, when I debugged using the Chrome (Network) tools, I noticed that the OPTIONS request was passing as shown below:

Here is the image of the POST error:

Here is another class that processes an OPTIONS request (JWTLoginFilter, as specified in WebSecurityConfig):
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter { public JWTLoginFilter(String url, AuthenticationManager authManager) { super(new AntPathRequestMatcher(url)); setAuthenticationManager(authManager); } @Override public Authentication attemptAuthentication( HttpServletRequest req, HttpServletResponse res) throws AuthenticationException, IOException, ServletException { AccountCredentials creds = new ObjectMapper() .readValue(req.getInputStream(), AccountCredentials.class); if (CorsUtils.isPreFlightRequest(req)) { res.setStatus(HttpServletResponse.SC_OK); return null; } return getAuthenticationManager().authenticate( new UsernamePasswordAuthenticationToken( creds.getUsername(), creds.getPassword(), Collections.emptyList() ) ); } @Override protected void successfulAuthentication( HttpServletRequest req, HttpServletResponse res, FilterChain chain, Authentication auth) throws IOException, ServletException { TokenAuthenticationService .addAuthentication(res, auth.getName()); } }