2

I have Spring Cloud gateway running on separate server with the following configuration:

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/*]':   (I also tried '[/**]':)
            allowedOrigins: "http://localhost:3000"
            allowedMethods:
              - GET
              - POST

But every time from React app I get:

Access to XMLHttpRequest at 'http://11.1.1.1:8080/api/support/tickets/create' 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.

Do you know how this issue an be solved for Spring Boot 2.6.2/Spring cloud 2021.0.0?

Full code: http://www.github.com/rcbandit111/Spring_Cloud_Gateway_POC

POST Request:

Request URL: http://1.1.1.1:8080/api/merchants/onboarding/bank_details
Referrer Policy: strict-origin-when-cross-origin
Accept: application/json, text/plain, */*
Content-Type: application/json
Referer: http://localhost:3000/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36

Post request Payload:
{"currency":"HNL","iban":"dssvsdvsdv"}

OPTIONS request:

Request URL: http://1.1.1.1:8080/api/merchants/onboarding/bank_details
Request Method: OPTIONS
Status Code: 403 Forbidden
Remote Address: 1.1.1.1:8080
Referrer Policy: strict-origin-when-cross-origin

Response:

HTTP/1.1 403 Forbidden
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
content-length: 0

OPTIONS Request headers:

OPTIONS /api/merchants/onboarding/bank_details HTTP/1.1
Host: 1.1.1.1:8080
Connection: keep-alive
Accept: */*
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36
Sec-Fetch-Mode: cors
Referer: http://localhost:3000/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Peter Penzov
  • 2,352
  • 100
  • 358
  • 675

3 Answers3

2

Are you running your FE app via --proxy-conf to redirect? I am not a well versed in FE, but dont use changeOrigin: true. If you have to to use changeOrigin: true, it will only work for GET and for others you might have to do something like this. To use proxy-conf, we usually have a proxy.conf.json with something like this:

{
  "/api/*": {
    "target": "http://external-gateway-url",
    "secure": false,
    "logLevel": "debug"
  }
}

and then while running the app use --proxy-config proxy.conf.json. My FE knowledge is out-of-date. You may want to look something like this.

If not, and the call is direct, just the following configuration (also needed for proxy too) in gateway should work:

spring:
  cloud:
    gateway:
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedOrigins: "http://localhost:3000"
            allowedHeaders: "*"
            allowedMethods:
            - GET
            - POST
Dhananjay
  • 955
  • 1
  • 10
  • 25
  • no, I don't use ` --proxy-conf` – Peter Penzov Jan 08 '22 at 02:29
  • So your java script is configured with the host name as well? Meaning in the network tab, call is made from localhost:3000 to gateway http://1.1.1.1:8080? – Dhananjay Jan 08 '22 at 03:26
  • I notice, you dont have `allowedHeaders: "*"` in the configuration – Dhananjay Jan 08 '22 at 03:36
  • Strange, again it's not working. Can I invite you tomorrow on a call and share my screen to show you in details the issue? Can you share your mail for example, please? – Peter Penzov Jan 08 '22 at 03:49
  • Not sure about the call, its weekend :) Can you try using proxy-conf? I will update the answer – Dhananjay Jan 08 '22 at 03:55
  • I found the issue: https://stackoverflow.com/questions/70637808/disable-options-request-before-post-in-react Any idea for a solution? – Peter Penzov Jan 09 '22 at 01:46
  • OPTIONS is something that browser do when there is a call made to a different origin. Dont think you can control that. You can check the repose-headers from the options call to verify if Gateway is configured correctly. – Dhananjay Jan 09 '22 at 16:51
  • If Gateway is not under your control, you could look into using --proxy-conf, a feature by webpack. CORS is a browser-to-server check. Its doesnt happend with backend-to-backend calls. With proxy, you will just re making calls to the webpack server which in turn will be redirecting it to an external server. – Dhananjay Jan 09 '22 at 16:54
  • The issue is a bug in Spring Cloud Gateway - OPTIONS requests are blocked so this breaks POST and DELETE requests. – Peter Penzov Jan 09 '22 at 17:06
  • See here https://github.com/spring-cloud/spring-cloud-gateway/issues/112 and here https://github.com/spring-cloud/spring-cloud-gateway/issues/2472 – Peter Penzov Jan 09 '22 at 17:07
  • Not sure if its a bug. You could wait for spring team to respond. But note that CORS check kicks in when there is a "Origin" header in the request. For GET I dont thinks it's their, but for POST/PUT it is typically there. Enble wiretab logs in gateway to check - https://cloud.spring.io/spring-cloud-gateway/reference/html/#wiretap – Dhananjay Jan 09 '22 at 17:19
  • With postman things, will work fine as its not a bowser call, which adds these headers. – Dhananjay Jan 09 '22 at 17:20
  • I send API requests from React app to remote VPS server - CORS should be blocking requests only if all apps are on the same machine. – Peter Penzov Jan 09 '22 at 17:21
  • Yes with POSTMAN I can make successful POST and DELETE requests. – Peter Penzov Jan 09 '22 at 17:21
  • Check about origin - https://developer.mozilla.org/en-US/docs/Glossary/Origin If anything in domain changes, its a different origin – Dhananjay Jan 09 '22 at 17:25
  • Just enable wiretap logs and check Origin header when the reques is from browser vs when it is from postman. – Dhananjay Jan 09 '22 at 17:26
1

Check out the section entitled Simple requests in the MDN Web Docs about CORS:

The only type/subtype combinations allowed for the media type specified in the Content-Type header are:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

Because you use the value application/json for your request's Content-Type header, you need to allow that header in your CORS configuration:

cors-configurations:
  '[/**]':
    allowedOrigins: "http://localhost:3000"
    allowedMethods:
      - GET
      - POST
    allowedHeaders:
      - Content-Type

jub0bs
  • 54,300
  • 24
  • 162
  • 166
  • Do you know how I can configure this using Java Bean configuration? – Peter Penzov Jan 06 '22 at 12:02
  • @PeterPenzov No. That would be a different question anyway. – jub0bs Jan 06 '22 at 12:03
  • @PeterPenzov Have you tried the solution above? – jub0bs Jan 06 '22 at 12:08
  • I will try it later today and let you know hat is the result. – Peter Penzov Jan 06 '22 at 12:08
  • I get again `Access to XMLHttpRequest at 'http://1.1.1.1:8080/api/merchants/onboarding/countries' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.` – Peter Penzov Jan 07 '22 at 00:06
  • @PeterPenzov Well, that's progress: no mention of the preflight this time, which means it succeeded. Now the actual request is failing, for some reason. Can you add a screenshot of the response to the actual (`POST`) request? – jub0bs Jan 07 '22 at 09:19
  • Please see this post description: https://stackoverflow.com/questions/70561543/configure-cors-policy-for-spring-cloud-gateway I added the payload there – Peter Penzov Jan 07 '22 at 09:36
  • @PeterPenzov You haven't added the response to the POST request. Based on the error message you're now getting, you should now get a response to that request. – jub0bs Jan 07 '22 at 09:49
  • 1
    I will make again later today test requests and let you know about the result. – Peter Penzov Jan 07 '22 at 09:49
1

I had a similar Problem and i did the following:

My application.yml contains to add the CORS Configuration to every route:

spring:
  cloud:
    gateway:
      globalcors:
        add-to-simple-url-handler-mapping: true

Then I configured a spring standard CorsWebFilter Bean. Note for production you should not use * for the AllowedOrigins property. For Development purpose this is perfectly fine.

@Configuration
public class CorsConfiguration extends org.springframework.web.cors.CorsConfiguration {

  @Bean
  public CorsWebFilter corsFilter() {
    org.springframework.web.cors.CorsConfiguration corsConfiguration = new org.springframework.web.cors.CorsConfiguration();
    corsConfiguration.setAllowCredentials(true);
    corsConfiguration.addAllowedOrigin("*");
    corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD"));
    corsConfiguration.addAllowedHeader("origin");
    corsConfiguration.addAllowedHeader("content-type");
    corsConfiguration.addAllowedHeader("accept");
    corsConfiguration.addAllowedHeader("authorization");
    corsConfiguration.addAllowedHeader("cookie");
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", corsConfiguration);
    return new CorsWebFilter(source);
  }
}

Note: I have the Version 2.3.9.Release for spring boot and spring cloud version is Hoxton.SR10 .

Tr1monster
  • 106
  • 2
  • 8
  • I tried the code but I get https://pastebin.com/72REGwi8 with latest stable Spring Cloud. Any idea for a solution? – Peter Penzov Jan 07 '22 at 00:01
  • I expect that * is not allowed anymore. So maybe try `corsConfiguration.setAllowedOrigin("")` – Tr1monster Jan 07 '22 at 07:32
  • One additional question: I run Spring Cloud Gateway on a remote VPS server and I run run React application on my local PC. I think in that case CORS should not make a problem. Did you had a such case? – Peter Penzov Jan 07 '22 at 08:21
  • I'm not realy sure about it. But if it is a problem then you may consider running an second gateway on your local machine. So your traffic look like: react app -> local gateway (Here you have to configure cors. Different ports on localhost are different origins!) -> gateway on VPS server. – Tr1monster Jan 07 '22 at 08:46
  • Maybe I need to configure something in React app? – Peter Penzov Jan 07 '22 at 09:00
  • There's never a need to allow the `origin` or `cookie` request headers. Moreover, you cannot use the wildcard (`*`) in conjunction with credentialed requests; see https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#credentialed_requests_and_wildcards – jub0bs Jan 09 '22 at 10:07