In spy movies, security operatives have a coded way of transmitting information amongst themselves. Since they are mostly transmitting information that can be used against them if it falls in the hands of their enemies, they have to make sure that those who are receiving the information are trusted parties. The same applies to those who are sending the said information. When the sender and receiver are trusted, the credibility and security of the information can be guaranteed. A replica of this scenario happens in the communication between browsers and web servers, and it is called the same-origin policy.

What is the Same-Origin Policy?

Have you ever noticed that web pages can’t access resources from a different website? That’s because of the Same-Origin Policy, which is a security feature in web browsers that prevents web pages from accessing resources (like cookies, scripts, and other data) from a different domain than the one that served the page. An origin is defined by the combination of the protocol, domain, and port number of a URL. Most browsers, including Chrome, Firefox, Safari, and Edge, implement a same-origin policy to keep your data safe. Now, why do we need this policy? To understand this, let us take a look at how the Internet works. You visit a website, your browser sends a request to the server hosting that website, and the server responds by sending back the resources needed to display the page. These resources might include HTML, CSS, JavaScript, and images.  Imagine that a web page could also make requests to other domains. To continue with our spy movie premise, a secret operative from another agency wants to get in touch with an agent from a different organization or country, request access, and share information. If they are granted this opportunity, it opens up the later organization to huge security vulnerabilities. They can steal sensitive information and potentially harm them.  The same-origin policy is in place to precisely tackle this problem. Although there are some misunderstandings about SOP, it doesn’t mean you can’t load resources from different origins or send information to another origin.  However, SOP sets rules that limit access and interaction between different resources, like scripts, CSS, iframes, images, and videos. It is like a guard that keeps web pages in their own domain and prevents them from accessing resources from other domains.  This keeps you safe from malicious attacks that could steal your data or trick you into performing unwanted actions.

What is CORS?

In a real-life case, when security operatives give a rule that communication should only happen amongst its operatives as a means of security, that’s similar to the same-origin policy. Yet, there might be cases where they will need to interact with the outside world. Or with operatives of other security outfits, for that to happen, they can implement another security measure to verify those operatives. This verification can come in different ways, depending on the operatives involved. In the case of communication on the Internet, CORS is the mechanism that makes it possible for browsers use to access resources that they originally will not be able to because the resource is of a different origin. I have talked about origin more than once, and you’re probably wondering what that means. An origin is defined by the protocol, domain, and port of the URL. When you have your API at an origin like https://api.geekflare.com:3001 and your frontend at https://geekflare.com, the origins are said to be different. In this situation, you’ll need CORS to be able to access resources on both ends. When requests are made to a server, the browsers (client) and servers send requests and response, HTTP headers are included. Amongst these headers, additional headers are included to prevent the browser from blocking the communication. Why will the browser block the communication? Its browser security features. It will do so if the request is coming from an origin different from that of the client. The additional headers included as a result of CORS is a way of telling the client that it can make use of the response that it received.

Common Issues with CORS

As a web developer, you need access to resources from different domains – like when building a web application that uses APIs from multiple sources. You implement CORS, which allows web servers to specify which other domains are allowed to access their resources, so you can still build the web apps you want. This behavior is implemented on the server side, so it cannot be reconfigured on the client side.  If you encounter a CORS error, it means that the server has denied your request to access its resources from a different domain because it doesn’t meet the required security standards. This can happen if the server doesn’t have the right settings in place. But don’t worry – there’s an easy way to fix it. Just make sure to check that the Access-Control-Allow-Origin header is correctly configured. This tells the server which domains are allowed to access its resources, so if it’s not set up correctly, you might run into problems. Here are some other issues you may encounter: 

If you’re trying to use a non-simple HTTP method (like DELETE or PUT) in a Cross-Origin resource-sharing request, it’s important to make sure that the server allows it. Browsers only allow simple methods by default, so you’ll need to explicitly set the Access-Control-Allow-Methods header if you want to use a different method. Also, while making such requests, you need to be careful about sending credentials (like cookies or authorization headers) from the browser that the server allows.   Moreover, the server will not respond correctly if the “preflight” inquiry for a non-simple request (like one with custom headers) reveals that it is unsupported. If a web page tries to access resources (hosted on a Content Delivery Network) such as images, scripts, or stylesheets from a different domain, the server hosting the resource might not allow requests from the domain that the page is hosted on. 

Luckily, there are a few ways to resolve this problem. One solution is to configure the server to allow cross-origin requests by sending the appropriate headers. Another option is to use a proxy server to make the request on behalf of your web application or to use JSON-P to wrap the response in a callback function. Furthermore, there are libraries that simplify cross-origin requests on the client side by handling the headers and providing a request API without issues. By trying these different solutions, you can work around these problems and ensure that your web application can access the resources it needs to function properly. A word of caution – these techniques can have their own security risks, so it’s important to use them carefully!

CORS Headers

One of the secure headers which can be either response or request header.

Response Headers

These are the headers that the server sends back in its response.

Access-Control-Allow-Origin: : This is used to specify the origin allowed to access the resource on the server. It’s possible to specify that only requests from a specific origin are allowed – Access-Control-Allow-Origin: https://geekflare.com, or that the origin does not matter – Access-Control-Allow-Origin: *. Access-Control-Expose-Headers: : As the name implies, this lists the headers the browser has access to. Access-Control-Max-Age: : This indicates the duration for which the response of a preflight request can be cached. Access-Control-Allow-Credentials: : This indicates that the browser can make use of the response when the initial request was made with a credential. Access-Control-Allow-Methods: : This indicates the method(s) that allowed when attempting to access a resource. Access-Control-Allow-Headers: : This indicates the HTTP headers can be used in a request.

Here is an example of what the response will look like

Request Headers

Here are the headers that a client’s request should contain in order to make use of the CORS mechanism.

Origin: : This indicates the origin of the client’s request. When working with a frontend and backend, as stated before, this will be the host of your frontend application. Access-Control-Request-Method: : This is used in a preflight request to indicate the HTTP method that will be used to make the request. Access-Control-Request-Headers:

: This is used in a preflight request to indicate the HTTP headers that will be used to make the request.

Here is an example of what a request will look like

Preflight Requests

After mentioning preflight requests here and there, what could it possibly mean? Preflight requests happen when the client has to send a preflight request before the main request. The preflight request is more of a probe to determine if the server supports the main request that’s about to be made. When positive confirmation is obtained, the main request is then sent. When a request is not a preflight request, it is called a simple request.

Implementing CORS

You mostly will want to set up things at the backend of your application. The implementation depends on the framework you are using. For this tutorial, we will look at how to do it in NodeJS and Rails.

Rails

I recommend you make use of the rack-cors gem. Then you’ll need to add this to your config/application.rb file.

NodeJS

In Node.js, this will look like this. In the code snippet, we are setting up the origin, methods, headers, and credentials that should be allowed to access the resources available on our server. And to implement in Apache or Nginx, refer to this guide. Conclusion CORS relaxes the policy so that your browser can access the resources you want it to. Understanding what it is, why it’s essential, and how to set it up will help in figuring out the issues you might face as you build your web applications.

CORS Explained  Importance of Cross Domain Resource Sharing in Web Development - 70CORS Explained  Importance of Cross Domain Resource Sharing in Web Development - 55CORS Explained  Importance of Cross Domain Resource Sharing in Web Development - 42CORS Explained  Importance of Cross Domain Resource Sharing in Web Development - 14