Spring Authorization Server: Access to XMLHttpRequest has been blocked by CORS policy - spring-boot

I have a basic Spring Authorization Server set up as a Spring Boot application. I am attempting to access this server via an angular application using angular-auth-oidc-client.
When I attempt to log in, I get this error:
Access to XMLHttpRequest at 'http://localhost:9000/mydomain/.well-known/openid-configuration' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I've made multiple attempts to fix this issue, but have been unsuccessful.
Relevant parts of the Configuration for the authorization server are below:
// #formatter:off
#Bean
public RegisteredClientRepository registeredClientRepository() {
// removed
}
// #formatter:on
#Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(Arrays.asList("*"));
config.setAllowedMethods(Arrays.asList("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH"));
config.setAllowedHeaders(Arrays.asList("*"));
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
// #formatter:off
#Bean
#Order(Ordered.HIGHEST_PRECEDENCE)
public SecurityFilterChain authServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http
.formLogin(Customizer.withDefaults())
.cors().configurationSource(corsConfigurationSource());
return http.build();
}
// #formatter:on
That CORS Configuration seems to be wide open, but I'm still seeing the issue.
Am I just making a stupid mistake that I'm not seeing?
Edit: yes, I've configured that port and domain in application.yml:
server:
port: 9000
servlet:
context-path: /mydomain

Related

Spring Security: CORS blocks POST requests, but GET, PUT and DELETE are working

I have the following CORS configuration on my spring gateway:
#Configuration
#EnableWebFluxSecurity
public class GatewayConfig {
#Bean
public CorsWebFilter corsWebFilter() {
final CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.setAllowedOrigins(Collections.singletonList("*"));
corsConfig.setMaxAge(3600L);
corsConfig.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
corsConfig.addAllowedHeader("*");
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfig);
return new CorsWebFilter(source);
}
}
It works perfectly fine with the GET, PUT and DELETE requests, but any POST request returns:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at <service-url>. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 302
Update:
Actually, for some reason it only blocks POST request on one route only.
This is the security configuration:
protected void configure(HttpSecurity http) throws Exception {
// Validate tokens through configured OpenID Provider
http.oauth2ResourceServer().jwt().jwtAuthenticationConverter(jwtAuthenticationConverter());
// Service security setup
http
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/polls").hasRole("ADMIN")
.antMatchers(HttpMethod.PUT, "/polls/*").hasRole("ADMIN")
.antMatchers(HttpMethod.DELETE, "/polls/*").hasRole("ADMIN")
.antMatchers(HttpMethod.POST, "/polls/{author:[\\s\\S]+}/vote").authenticated()
.antMatchers(HttpMethod.POST, "/polls/*").hasRole("ADMIN")
.anyRequest().permitAll();
}
CORS only blocks POST requests on the "/polls" route, while every other request works fine

Setting CORS headers with spring-security OAuth

I've trying to set CORS headers for a OAuth Rest API:
#Configuration
#EnableWebSecurity
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.cors().and()
.authorizeRequests()
.antMatchers("/oauth/token", "/oauth/authorize**", "/publica")
.permitAll();
http.requestMatchers().antMatchers("/funds/**").and().authorizeRequests().antMatchers("/funds/**")
.access("hasRole('USER')");
...
However, I'm not seeing the CORS headers in the response (Postman, localhost) when I access /oauth/token:
No CORS headers e.g. Access-Control-Allow-Origin: * :(
Also, I'd like this setting to apply to all routes too (e.g. /funds) but just trying to get the /oauth/token route working first.
Do I have this in the correct place? How do I get the CORS headers to set for this /oauth/token route (and others)? As far as I'm aware, the default corsConfigurationSource ought to be picked up if defined.

App Engine Standard with Spring Boot CORS not working

I am implementing a Spring Boot application that is hosted on a Google App Engine Standard Environment.
I have configured CORS like this, following the official guide:
#Configuration
#EnableWebSecurity
class WebSecurityConfigurer : WebSecurityConfigurerAdapter() {
#Throws(Exception::class)
override fun configure(http: HttpSecurity) {
http.csrf()
.disable()
.cors()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().authorizeRequests().antMatchers("/api/**").permitAll()
}
#Bean
fun corsConfigurationSource(): CorsConfigurationSource {
val configuration = CorsConfiguration()
configuration.allowedOrigins = listOf("*")
configuration.allowedMethods = listOf("GET", "POST", "OPTIONS", "PUT", "DELETE", "HEAD")
val source = UrlBasedCorsConfigurationSource()
source.registerCorsConfiguration("/**", configuration)
return source
}
executing the following cURL I receive the AllowedOrigins header as it is necessary:
curl -H "Access-Control-Request-Method: GET" -H "Origin: http://foo" -X OPTIONS "localhost:8080/api/abc/list?lang=de"
Response:
HTTP/1.1 200
Access-Control-Allow-Origin: *
Now when I have deployed my Spring App to AppEngine, I can also cURL successfully.
HTTP/2 200
access-control-allow-origin: https://myfrontend.com
access-control-allow-methods: GET
access-control-allow-credentials: true
Unfortunately, my Frontend Application gets blocked with a 403
Access to fetch at 'https://mybackend.com/api/abc/list?lang=de' from origin 'https://myfrontend.com' 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. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Any tips?
Thanks.
I think you missed the important part setting headers in cors.
Add this line
configuration.allowedHeaders = listOf("*")
I used this code :
Ref : https://blogs.ashrithgn.com/disable-cors-in-spring-boot/
I have two GAE project
Python based using angular 11
Spring boot based micro services std env
Imp : No other changes in app.yaml or as mentioned by spring at
https://spring.io/guides/gs/rest-service-cors/ will make any difference
#Configuration
public class CorsConfig {
#Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
}

Simple CORS setup is not working by adopting all means

The frontend server is running on localhost:8080 and try to do CORS PUT request to the Spring boot server running on localhost:1072
I googled all the possible solution to make the CORS request work.
However, it's only working by using Postman for the PUT request.
Got 401 on the Chrome browser.
How do I make the Spring server could take CORS requests.
Thanks!
Also, curious why Spring doesn't show the exception on the console and always give developers hard time lol
CORSConfig.java
#Configuration
public class CORSConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://localhost:8080");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
registry.addMapping("/**")
.allowedMethods("*").allowedOrigins("*");
}
}
WebSecurityConfig.java
#Override
protected void configure(HttpSecurity http) throws Exception {
if (h2ConsoleEnabled)
http.authorizeRequests()
.antMatchers("/h2-console", "/h2-console/**").permitAll()
.and()
.headers().frameOptions().sameOrigin();
http.csrf().disable()
.cors()
.and()
.exceptionHandling().authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/v1/**","/articles/**", "/profiles/**", "/tags").permitAll()
.antMatchers(HttpMethod.PUT, "/v1/**","/articles/**", "/profiles/**", "/tags").permitAll()
.antMatchers(HttpMethod.POST, "/v1/**","/articles/**", "/profiles/**", "/tags").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(jwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
#Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
configuration.addAllowedOrigin("*");
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
ArticleApi.java
#CrossOrigin(origins = "*")
#RestController
#RequestMapping(path = "/v1/groups/{groupId}/articles/{aId}")
public class ArticleApi {
#CrossOrigin(origins = "*")
#PutMapping
public String updateArticle(#PathVariable("groupId") String groupId,
#PathVariable("aId") String aId
) {
return
}
The 401 reponse is received when the pre-flight check for the CORS request fails. So, it might be that your cors is not setup correctly.When reading through your config it made the following observations :
If you are going to allow cross origin requests from all domains on all methods, you could remove the controller method level annotation #CrossOrigin(origins = "*") as it is already specified at class level.
You are providing two global configurations for the CORS config. One config with the bean order set as 0 accepts only origin http://localhost:8080 while that configured with spring security accepts all origin.Remove one and keep either of the two as per your need.
You could try removing the CORS configuration provided in the class CORSConfig. You have already provided cors configuration along with WebSecurityConfig. You could remove the cors configuration provided in the security config,either way it will work with just one configuration or try removing the below code :
#Configuration
public class CORSConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://localhost:8080");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
registry.addMapping("/**")
.allowedMethods("*").allowedOrigins("*");
}
}

Unauthorized Error when using jHipster oAuth despite CORS

I am running a jHipster instance with oAuth authentication and CORS enabled on the server. I've added the following bean:
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.setAllowedMethods(Arrays.asList(new String[]{"GET", "PUT", "POST", "DELETE", "OPTIONS"}));
source.registerCorsConfiguration("/api/**", config);
source.registerCorsConfiguration("/v2/api-docs", config);
source.registerCorsConfiguration("/oauth/**", config);
return new CorsFilter(source);
}
and added .antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll() to ResourceServerConfiguration configuration.
When I attempt to authenticate a user (using jHipster running on a server) from an app running locally on a browser, I get:
Request Method:OPTIONS - Status Code:401 Unauthorized
It seems CORS is not configured properly to handle pre-flight authentication POST requests.
I've tried to implement some solutions proposed at Spring Data Rest and Cors and Spring Data Rest and Cors to no avail.
Is this something specific that can be done in jHipster to enabled authentication to work from a browser or app (not running on the jhipster server)?
I uncommented lines of CORS
cors: #By default CORS are not enabled. Uncomment to enable.
allowed-origins: "*"
allowed-methods: GET, PUT, POST, DELETE, OPTIONS
allowed-headers: "*"
exposed-headers:
allow-credentials: true
max-age: 1800
Added in SecurityConfiguration
**.antMatchers(HttpMethod.OPTIONS, "/**")**
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(HttpMethod.OPTIONS, "/**")
.antMatchers("/scripts/**/*.{js,html}")
.antMatchers("/bower_components/**")
.antMatchers("/i18n/**")
.antMatchers("/assets/**")
.antMatchers("/swagger-ui/index.html")
.antMatchers("/api/register")
.antMatchers("/api/activate")
.antMatchers("/api/login/**")
.antMatchers("/api/account/reset_password/init")
.antMatchers("/api/account/reset_password/finish")
.antMatchers("/test/**");
}
And it has been working so far.

Resources