Issue
I am trying to set the minimal headers to allow CORS to the same machine on different ports. I am using the latest SpringBoot and SpringSecurity as of writing theses lines. The documentation is poor and the examples are not extensive enough.
I find myself wasting too many hours on trying to figure out how to do things right, yet without success.
Bellow is my last try to configure CORS.
If any of you has any idea why ORIGIN headers are missing and how to enable them, that would be greatly appreciated.
TIA, Asaf Gery
package com.madas.restapi;
import java.util.Arrays;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.header.writers.ContentSecurityPolicyHeaderWriter;
import org.springframework.security.web.header.writers.CrossOriginResourcePolicyHeaderWriter;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authz) -> authz
.anyRequest().permitAll()
)
.headers(headers -> headers
.addHeaderWriter(new CrossOriginResourcePolicyHeaderWriter())
.addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN))
.addHeaderWriter(new ContentSecurityPolicyHeaderWriter("object-src localhost;"))
);
return http.build();
}
}
Solution
The problem with Spring Framework, is that every few versions they break their own API and invent a new way to do the same things. This practice makes Stack Overflow less useful, since it holds many historical solutions that worked for previous versions but no longer work.
So, the minimal way to enable CORS in Spring Security 5.7.3 (and probably all Spring 5.7.x versions), without any limitation on host/port, etc. (i.e. permit all), is as follows:
Configuration
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class RestConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/resource").permitAll();
return http.build();
}
}
Controller
...
@GetMapping("/resource")
@CrossOrigin(
// Access-Control-Allow-Origin
origins = { "*" },
// Alternative to origins that supports more flexible originpatterns.
// Please, see CorsConfiguration.setAllowedOriginPatterns(List)for details.
// originPatterns = { "" },
// Access-Control-Allow-Credentials
allowCredentials = "false",
// Access-Control-Allow-Headers
allowedHeaders = { "*" },
// Access-Control-Expose-Headers
exposedHeaders = { "*" },
// Access-Control-Max-Age
maxAge = 60 * 30,
// Access-Control-Allow-Methods
methods = {RequestMethod.GET}
)
public @ResponseBody ResponseEntity<CollectionModel<EntityModel<Resource>>> get() {
...
}
Answered By - Asaf Gery
Answer Checked By - Willingham (JavaFixing Volunteer)