Make Sense of CORS Fixes

Photo by Peter Bosch on Unsplash

Make Sense of CORS Fixes

image.png

Any Front-end dev building modern web apps would feel very familiar with this error in the browser console, and most likely have fixed it several times with some magic snippets found from Google. But this time let's dig in a bit more to better understand why these fixes work.

What CORS is

It all starts with the the default browser security mechanism same-origin policy, which does not allow AJAX requests sent to a different origin other than the one serving your web page and JS files.

A origin is a combination of protocol, host and port. So CORS (Cross-Origin Resource Sharing) is a security relaxation to get around this browser security feature as sometimes we do need to allow requests to go to another origin for legitimate reasons as commonly seen in the SPA setup. (e.g api server is hosted separately or need to communicate to external api)

Why CORS is needed

As described in What, it is to get around the same-origin policy. But why we have this policy in the first place? Well browser is like a crowded marketplace where any link can be opened here, same origin is like providing a safe sandbox to isolate pages from different sites. Consider the contrived scenario below:

image.png

Thanks to the same-origin policy, the fake site cannot take advantage of the credentials stored in browser cookie and make requests to the actual server to possibly gain access to protected resources or perform harmful actions. So you money is safe 💰

Now imagine the server is hosted in another origin (different host), we want the real web page to still be able to communicate with the server but block the fake page's requests as same-origin. This is what CORS comes to mitigate.

How CORS works

In general, it works by setting a few HTTP Headers between browser and web server. Depending on if the request is a simple request, the flow will be different as simple requests normally do not cause side effect on server resources, e.g change status or delete resources.

▪︎ Simple Request Flow:

image.png

In this case, browser directly sends the simple request with header origin: https://app.domain.com. If server returns response with header access-control-allow-origin containing the origin in the request, the browser will continue to consume the response.

▪︎ Preflight Request Flow:

cors-preflight-animation

When the request does not meet the simple request criterias, (e.g request method is DELETE or contain custom headers ), as shown in above animation, this time browser will first send a preflight request with method: OPTIONS. It basically says:

"I want to make a POST request to api.domain.com" from app.domain.com with Content-Type, Accept and custom Authorization headers, is this allowed?"

If the server responds with a set of Access-Control-* headers covering those requested in OPTIONS request, the actual POST request will be sent.

In browser network tab, you probably have noticed sometimes there are prefligt request sent before the real one.

OPTIONS.png

Check this article for Reduce preflight overhead

▪︎ Request with Credentials

The last scenario is when request contains credentials, e.g cookie header. It has the same flow as either simple or preflight, but require extra response header Access-Control-Allow-Credentials: true, and must not use * wildcard in other Access-Control-* headers.

That's it, thanks for reading the first post! Hopefully with this quick guide it makes more sense when you search around fixes for the CORS errors.

Reference

MDN CORS Doc
Complete Guide to CORS
3 Ways to Fix the CORS
Visualised Explanation for CORS

Drawing with Excalidraw, and this nice tool built by @dai_shi to make drawing animate