CORS - Cross-Origin Resource Sharing

security javascript

Dec 31 2023 14:51

If you're working on your local development and try to consume api from internet, you face it some time

Access to fetch at 'http://localhost:4000/api' 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. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

What it is, when & why it happens

We can call it's an error thrown by Browser

Happen when site https://abc.com try to request to resource from site https://api.xyz.com but it now allow to do that, then Browser will blocks the request

The reason you are not allowed because https://api.xyz.com only accept request coming from https:/xyz.com or from allow config list

"My house, only me and my family can get in"

Solutions

Resource owner

If you're resource owner, you need to config CORS to allow access from expected site for example in Spring boot CORS config I allow http://localhost:3000 to access in development env, and public domain https://pdminh.dev access in prod env

if (Arrays.stream(environment.getActiveProfiles()).anyMatch(p -> p.equals("dev"))) {  
    corsConfiguration.setAllowedOrigins(List.of("http://localhost:3000"));  
} else {  
    corsConfiguration.setAllowedOrigins(List.of("https://pdminh.dev"));  
}

Try to access localhost:4000/api from react localhost:3000 website, status is 200

image

Update my react app default port to 3001, get CORS error in consolog and status 403

image

Access to fetch at 'http://localhost:4000/api/weatherapi/v1/current.json?key=23ad9903220e4d1196243159231502&q=da+nang' from origin 'http://localhost:3001' 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.

You can also set allow origin to * to allow every where to access, the api of public service will set allow * for everyone to request

If you're not resource owner

As i said above, it's a error throw by Browser, you can access the api via postman or any application (not browser)

image

But the problem is you want to use the api in you react app, so you will need a proxy server to by pass browser block

image

Proxy server is just a web server that has function to forward request As a Java developer, I use Spring Zuul to build proxy server. Example available here Github

If you build your react app with nextjs, it already has function called rewrites which works the same

module.exports = () => {
  const rewrites = () => {
    return [
      {
        source: "/pdminhdevapi",
        destination: "https://api.pdminh.dev",
      },
    ];
  };
  return {
    rewrites,
  };
};

Conclusion

  • CORS error you see on console is a feature of Browser
  • CORS config in backend will strengthening web security
  • We can bypass browser block by use proxy server, but you need to understand how it works first. I found some small problem but take time to resolve, Ex

Access to fetch at 'http://localhost:4000/api/weatherapi/v1/current.json?key=23ad9903220e4d1196243159231502&q=da+nang' from origin 'http://localhost:3000' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values 'http://localhost:3000, \*', but only one is allowed. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

It happened cause the proxy and the origin server both add Access-Control-Allow-Origin header I solved this problem by ignore header 'Access-Control-Allow-Origin' return from origin server

image

me

Pham Duc Minh

Da Nang, Vietnam