I am getting this error CORS even though I had already config CORS in Spring boot CORS Error But it's working with the GET Method
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:5173")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.exposedHeaders("Authorization")
.allowCredentials(true);
}
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests((auth) -> auth
.requestMatchers("/auth/**", "/drive/**").permitAll()
.requestMatchers("/enrollments/**").hasAnyAuthority("LECTURER", "STUDENT")
.requestMatchers(HttpMethod.POST, "/courses/**").hasAuthority("LECTURER")
.requestMatchers(HttpMethod.GET, "/courses/**").hasAnyAuthority("LECTURER", "STUDENT")
.requestMatchers(HttpMethod.POST, "/school/**").hasAuthority("LECTURER")
.requestMatchers(HttpMethod.GET, "/school/**").hasAnyAuthority("LECTURER", "STUDENT")
)
.sessionManagement(manager -> manager.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authenticationProvider(authenticationProvider())
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
return httpSecurity.build();
}
and I call API in React:
const createNewCourse = async () => {
const res = await axiosInstance.post(
'/courses/new-course',
{
userIds: selectedStudents,
},
{
params: {
title: courseTitle,
lecturerId: user?.userId,
},
withCredentials: true,
}
);
...
};
I have already researched but it still does not work.
I am getting this error CORS even though I had already config CORS in Spring boot CORS Error But it's working with the GET Method
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:5173")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.exposedHeaders("Authorization")
.allowCredentials(true);
}
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests((auth) -> auth
.requestMatchers("/auth/**", "/drive/**").permitAll()
.requestMatchers("/enrollments/**").hasAnyAuthority("LECTURER", "STUDENT")
.requestMatchers(HttpMethod.POST, "/courses/**").hasAuthority("LECTURER")
.requestMatchers(HttpMethod.GET, "/courses/**").hasAnyAuthority("LECTURER", "STUDENT")
.requestMatchers(HttpMethod.POST, "/school/**").hasAuthority("LECTURER")
.requestMatchers(HttpMethod.GET, "/school/**").hasAnyAuthority("LECTURER", "STUDENT")
)
.sessionManagement(manager -> manager.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authenticationProvider(authenticationProvider())
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
return httpSecurity.build();
}
and I call API in React:
const createNewCourse = async () => {
const res = await axiosInstance.post(
'/courses/new-course',
{
userIds: selectedStudents,
},
{
params: {
title: courseTitle,
lecturerId: user?.userId,
},
withCredentials: true,
}
);
...
};
I have already researched but it still does not work.
This is due to SpringSecurity intercepting your OPTIONS
preflight requests, causing the OPTIONS
to respond 401
, resulting in a CORS error.This is because Spring Security uses a "deny first" security policy by default.
In your configuration, if a request is not explicitly matched by any rule, the default rule is applied:
.anyRequest().authenticated()
You need to modify your SpringSecurity configuration slightly so that it releases all preflight requests.
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests((auth) -> auth
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() // Add this line
.requestMatchers("/auth/**", "/drive/**").permitAll()
.requestMatchers("/enrollments/**").hasAnyAuthority("LECTURER", "STUDENT")
.requestMatchers(HttpMethod.POST, "/courses/**").hasAuthority("LECTURER")
.requestMatchers(HttpMethod.GET, "/courses/**").hasAnyAuthority("LECTURER", "STUDENT")
.requestMatchers(HttpMethod.POST, "/school/**").hasAuthority("LECTURER")
.requestMatchers(HttpMethod.GET, "/school/**").hasAnyAuthority("LECTURER", "STUDENT")
)
.sessionManagement(manager -> manager.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authenticationProvider(authenticationProvider())
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
return httpSecurity.build();
}
This should work fine.
Another thing you may want to note is that SpringSecurity's security configuration is based on the rule that "the same Request is configured first to take effect, and later to be invalid
.requestMatchers( "/**").permitAll()
matches all your requests, then all configurations after that will be invalid.So you should take the above mentioned
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
Place it up front to keep it a high priority.
Hope this resolves your issue. Happy to provide more details if needed.
OPTIONS
request a 200 status or something else? – Phil Commented Jan 7 at 3:04