I am at a loss. I am trying to configure CORS
and I have tried just about everything I can find on the internet/Stack overflow.
Requests are working in Postman but not in React using axios.
Here is my function for deleting a user (this works in Postman
but not when triggered in React):
deleteEmployeeById(id) {
// return axios.delete(API_BASE_URL `employees/${id}`);
var testing = "";
return axios
.delete(API_BASE_URL `employees/${id}`, {
headers: {
Authorization: `Bearer ${HARDCODED_JWT_TESTING}`,
},
})
.then("yessssss")
.catch((error) => {
console.log("failed to delete emp by id" error);
});
}
}
I have a SecurityConfig.java file that looks like this:
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
MyUserDetailsService myUserDetailsService;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// TODO : use this line when i implement bcrypt
// auth.userDetailsService(myUserDetailsService).passwordEncoder(passwordEncoder());
auth.userDetailsService(myUserDetailsService);
}
// TODO : should use this password encoder
// public PasswordEncoder passwordEncoder() {
// return new BCryptPasswordEncoder();
// }
@Bean
public PasswordEncoder passwordEncoder() {
// TODO : not secure. Use a different encoder. testing only
return NoOpPasswordEncoder.getInstance();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// allow users to access "authenticate" page without being authenticated
// all other requests must be authenticated
// stateless tells it to not create a session? Do i need? Not sure yet
// http.csrf().disable().authorizeRequests().antMatchers("/api/authenticate").permitAll().anyRequest()
// .authenticated().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues()).and().csrf()
.disable().authorizeRequests().antMatchers("/api/authenticate").permitAll().anyRequest().authenticated()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
// create bean of type 'authenticationManager'
return super.authenticationManagerBean();
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setExposedHeaders(Arrays.asList("X-Auth-Token", "Authorization", "Access-Control-Allow-Origin",
"Access-Control-Allow-Credentials"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
I have no clue which function the error is in, but I assume it is the corsConfigurationSource()
method. However, I see no issue that this shouldn't work. It used to work before I attempted to add security to the app.
AS you can see in that method, I have set all of the allowed methods, I allow all origins, ect, but I still get this error when attempting to delete a user from my database:
Access to XMLHttpRequest at 'http://localhost:8080/api/employees/6151c89ea1b79f789a7a964b' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
This DOES work in Postman though. I can Delete a user no problem, it just will not work when triggered from my frontend React app.
It looks like I am allowing everything in CORS
, any idea what else is left to configure??
CodePudding user response:
Try removing .applyPermitDefaultValues()
call in SecurityConfig
after instantiating CorsConfiguration
. This is basically reseting CORS configuration to the defaults:
- Allow all origins with the special value "*" defined in the CORS spec. This is set only if neither origins nor originPatterns are already set.
- Allow "simple" methods GET, HEAD and POST.
- Allow all headers.
- Set max age to 1800 seconds (30 minutes).
Additionally, call corsConfigurationSource()
method instead of instantiating a new CorsConfiguration
.
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().configurationSource(corsConfigurationSource()).and().csrf()
.disable().authorizeRequests().antMatchers("/api/authenticate").permitAll().anyRequest().authenticated()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
Also, update your CorsConfigurationSource
as follows:
@Bean
CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
configuration.setAllowedMethods(Arrays.asList("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setExposedHeaders(Arrays.asList("X-Auth-Token", "Authorization", "Access-Control-Allow-Origin",
"Access-Control-Allow-Credentials"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
CodePudding user response:
For better clarity and for the purpose of testing, can you try testing your corsConfigurationSource()
by the following method.
Please do change the code as it fits to your application such as origin etc.
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
configuration.setAllowedMethods(Arrays.asList("*"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
It is basically allowing all headers, methods and origins. It is not ideal for production but for testing purpose you can try this. This may not solve the issue but we can start from here. Happy coding!