Reputation: 1425
Why is my 'Access-Control-Allow-Credentials' no longer being sent in response to preflight calls (OPTIONS) under Spring Boot 2.0.x (2.0.1.RELEASE in my case)? Here is my Global CORS Configuration that works fine under Spring Boot 1.5.6:
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins(
"http://localhost:3000",..)
.allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD");
}
};
}}
My pom dependencies (I am doing my own security and avoiding Spring Security):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
My service call to the REST endpoints fails the preflight:
Failed to load http://localhost:8080/api/v5/sec/auth: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. Origin 'http://localhost:3000' is therefore not allowed access.
I have verified that 'Access-Control-Allow-Credentials' header is indeed present in the case of Spring Boot 1.5.6 and missing under Spring Boot 2.0.1.
All the documentation I can find, including the latest on spring.io here, says my global configuration is still correct, even though WebMvcConfigurerAdapter appears to be deprecated now.
UPDATE:
Here are the response headers before and after the migrate:
Before Migrate (Spring Boot 1.5.6):
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:3000
Content-Type: application/json;charset=UTF-8
Date: Day, dd Mon yyyy hh:mm:ss GMT
Transfer-Encoding: chunked
Vary: Origin
After Migrate (Spring Boot 2.0.1 - Access-Control-Allow-Credentials header missing, but others changed/added):
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Methods: GET,HEAD,POST <-- My specified methods ignored
Access-Control-Allow-Origin: * <-- My specified origin ignored
Access-Control-Max-Age: 1800
Content-Length: 0
Date: Day, dd Mon yyyy hh:mm:ss GMT
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Upvotes: 19
Views: 26083
Reputation: 1425
This was missing from the Spring doc and many examples but the answer was very easy. I just saw the allowCredentials() method on CorsRegistry and added .allowCredentials(true) to the registry method chain and that added the Access-Control-Allow-Credentials header back in.
Also, I no longer use the deprecated WebMvcConfigurerAdapter, but now implement WebMvcConfigurer and override the addCorsMappings() method.
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins(
"http://localhost:3000",..)
.allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD")
.allowCredentials(true)
;
}
}
Upvotes: 44
Reputation: 3313
Step 1 : Spring already has a CorsFilter even though You can just register your own CorsFilter as a bean to provide your own cofiguration.
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(Collections.singletonList("http://localhost:3000")); // Provide list of origins if you want multiple origins
config.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept"));
config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "OPTIONS", "DELETE", "PATCH"));
config.setAllowCredentials(true);
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
Step 2 : Annotate the controller with @CrossOrigin
annotation.
Upvotes: 3
Reputation: 2270
This works for me (Kotlin):
@Configuration
class CorsConfig : WebMvcConfigurer {
override fun addCorsMappings(registry: CorsRegistry) {
registry.addMapping("/**")
}
}
Upvotes: 0
Reputation: 501
I'm using spring boot 2.0.2. I have the same issue, but I use the following code to fix it. Does anybody have the best way?
// Miss `Access-Control-Allow-Origin` header in response using this bean.
// @Bean
// CorsConfigurationSource corsConfigurationSource() {
// CorsConfiguration configuration = new CorsConfiguration();
// configuration.setAllowCredentials(true);
// configuration.setAllowedHeaders(Arrays.asList("Authorization", "Cache-Control", "Content-Type"));
// configuration.addAllowedMethod("*");
// configuration.setAllowedOrigins(this.getAllowedOrigins());
// UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
// source.registerCorsConfiguration("/**", configuration);
// return source;
// }
@Bean
public FilterRegistrationBean<CorsFilter> initCorsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedHeaders(Arrays.asList("Authorization", "Cache-Control", "Content-Type"));
config.addAllowedMethod("*");
config.setAllowedOrigins(this.getAllowedOrigins());
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
Upvotes: 4
Reputation: 394
If you are using Spring Boot 2.0.x
CORS support is disabled by default and is only enabled once the management.endpoints.web.cors.allowed-origins property has been set. The following configuration permits GET and POST calls from the example.com domain:
management.endpoints.web.cors.allowed-origins=http://example.com management.endpoints.web.cors.allowed-methods=GET,POST
For more information refer
Upvotes: 4