Everyone gets upset when there is a red error: Access to Blocked by CORS Policy on the control bar! While there are some quick ways to get rid of this mistake, today let’s take a look at what CORS actually does, and why is it actually our friend

❗️ IN this blog post, I will not explain HTTP basics. If you want to learn more about HTTP requests and responses, I wrote a short blog post about it a while ago at 🙂. In my case, I use HTTP/1.1 instead of HTTP/2, which doesn’t affect CORS.

On the front end, we often need to display data that is located somewhere else! Before we can display this data, the browser must first make a request to the server to get it! The client sends an HTTP request containing all the information the server needs to send this data back to the client 🙂

Suppose we try to make a request from www.mywebsite.com like api.website.com

😃 We just sent an HTTP request to the server and the server responded with the JSON data we requested.

Now let’s try to send the exact same request to another domain. Now we send the exact same request to api.website.com via www.anotherdomain.com

Wait, what? We send the exact same request, but this time the browser shows us a weird error?

We just saw what CORS can do! 💪🏼 Now let’s take a look at why this error occurred and what it really means.

✋🏼 Same-origin policy

There is something called the same origin policy in browsers. By default, we can only access resources that are on the same source as the requesting source! Such as request https://mywebsite.com/image1.png this resource is feasible

But when a resource is in a different (subdomain), protocol, or port, it is cross-source!

But why does the same-origin policy even exist?

Suppose the same-origin policy doesn’t exist, and you accidentally click on one of the many viral links your aunt sends you on Facebook. This link redirects you to an “evil website” that has an embedded IFrame that loads your bank’s website and successfully logs in with some set of cookies! 😬

The developers of this “evil site” enabled the site to access this IFrame and interact with the DOM content of your bank’s website in order to send money to their account on your behalf!

Yes… This is a huge security risk! We don’t want anyone to have access to everything 😧

Fortunately, the same origin policy helps us here! This policy ensures that we can only access resources from the same source.

In this case, the source www.evilwebsite.com tries from www.bank.com! The same origin policy prevents this from happening and ensures that developers of nefarious sites can’t just access our bank data 🥳

Ok, so…… What does this have to do with CORS?

🔥 Client CORS

Although the same origin policy actually only applies to scripts, browsers “extend” this policy for JavaScript requests: by default, we can only access resources from the same origin!

But… We often need to access cross-domain resources 🤔 our front end needs to interact with our back end apis to load data? To safely allow cross-domain requests, browsers use a mechanism called CORS! 🥳

CORS stands for cross-domain resource sharing. Although browsers do not allow us to access resources that are located at different sources, we can use CORS to slightly alter these security restrictions while still ensuring that we securely access these resources 🎉

User agents (such as browsers) can use the CORS mechanism to allow cross-domain requests that would otherwise be blocked based on the value of some CORS specific header in the HTTP response! ✅

When a cross-domain request is made, the client automatically adds an extra header to our HTTP request: Origin. The Originheader value is the source of the request!

In order for the browser to allow access to cross-domain resources, it needs some headers from the server response that specify whether this server will allow cross-domain requests!

💻 Server CORS

As server developers, we can ensure that cross-domain requests are allowed by adding additional response headers to the HTTP response, all beginning with Access-Control-*, based on the values of these CORS response headers. Browsers now allow us to access cross-domain requests that would normally be blocked by the same origin policy

Although we can use multiple CORS headers, the browser needs a header to Allow cross-source Access: access-Control-allow-Origin! 🙂 The value of this header specifies which sources are allowed to access the resources they request from the server.

If we are developing a server that https://mywebsite.com should be accessible, we can add the value of that field to the access-Control-Allow-Origin header!

This header is now added to the response the server sends back to the client. By adding the head of the same-origin policy will no longer stop we receive response from https://api.mywebsite.com.

The CORS mechanism in the browser checksAccess-Control-Allow-OriginWhether the value of header is equal toOriginThe value to be sent is 🤚🏼

In this case, we request the source is https://www.mywebsite.com, it is listed in the Access – Control – Allow – Origin in the response header!

Perfect! 🎉 We were able to successfully receive cross-domain resources! So what happens when we try to Access these resources from sources not listed in the Access-Control-Allow-Origin header? 🤔

Ah yes, CORS cause notorious mistakes that can be frustrating at times! But now we actually see that it makes perfect sense

The 'Access-Control-Allow-Origin' header has a value
 'https://www.mywebsite.com' that is not equal 
to the supplied origin. 
Copy the code

In this case, the source is https://www.anotherwebsite.com. However, the server does not provide this source in the list of permitted sources for the Access-Control-Allow-Origin title! CORS successfully intercepted the request and our code cannot access the retrieved data 😃

CORS also allows us to add the wildcard * as an allowed source value. This means that requests from all sources should have access to the requested resource, so be careful!

Access-control-allow-origin is one of the many CORS headers we can provide. Server developers can extend the server’s CORS policy to (disallow) allow certain requests! 💪 🏼

Another common heading is access-Control-allow-methods heading! CORS only allows cross-domain requests sent using the listed methods.

In this case, only requests with GET, POST, or PUT methods are allowed! Other methods such as PATCH or DELETE will be blocked ❌

Speaking of PUT, PATCH, and DELETE requests, CORS actually handles these requests differently! 🙃 These “non-simple” requests initiate something called precheck requests!

🚀 Precheck request

CORS has two types of requests: simple requests and precheck requests. Whether the request is simple or prechecked depends on some value in the request (don’t worry, you don’t have to remember that, haha).

When the request is a GETorPOST method and doesn’t have any custom headers, the request is easy! Any other requests, such as the PUT, PATCH, or DELETE methods with the request, will be prechecked.

Okay, but what does “precheck request” even mean, and why does this happen?

Before sending the actual request, the client generates a precheck request! The precheck Request contains information about the actual Request we are about to execute 🔥 in its access-Control-request -* header

This provides the server with information about the actual request the browser is trying to make: what the method of the request is, what the attached header is, and so on.

The server receives the precheck request and sends an empty HTTP response with the server CORS header! The browser receives a precheck response that contains no data other than the CORS header, and checks whether the HTTP request should be allowed! ✅

If this is the case, the browser sends the actual request to the server, and the server responds with the requested data!

However, if this is not the case, CORS will block the precheck request, and the actual request will never be sent ✋🏼

Prechecking requests is a good way to prevent us from accessing or modifying resources on servers that do not have any CORS policies enabled

The server is now protected from cross-domain requests that may not be needed 😃

💡 To reduce the number of round trips to our server, we can cache precheck responses by adding headers to access-Control-max-agecors requests! This way we can cache the precheck response and the browser can use it instead of sending a new precheck request!

🍪 certificate

By default, cookies, authorization headers, and TLS certificates are set only on same-origin requests! However, we might want to use these credentials in a cross-domain request. Maybe we want to include cookies in the request that the server can use to identify the user!

Although CORS does not contain credentials by default, we can change it by adding the Access-Control-allow-credentialSCors header! 🎉

If we want to include cookies and other authorization headers in our cross-domain request, we need to set the withCredentials field to true on the request and add the Access-Control-allow-credentials header to the response.

Done! We can now include credentials 🥳 in cross-domain requests

While I think we can all agree that CORS errors can be frustrating at times, it’s amazing how they enable us to make cross-domain requests safely in the browser

Obviously, there’s a lot more to same-origin policies and CORS than I can cover in this blog post! Fortunately, if you want to read more about it, there are lots of great resources like this one or the W3 specification 💪🏼