Wondering what is CORS (Cross-Origin Resource Sharing)?

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.

https://pt.slideshare.net/atirekgupta/selenium-workshop-34820044

A replica of this scenario happens in the communication between browsers and web servers, and it is called the same-origin policy.

According to MDN:

The same-origin policy is a critical security mechanism that restricts how a document or script loaded from one origin can interact with a resource from another origin. It helps isolate potentially malicious documents, reducing possible attack vectors.

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.

Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell browsers to give a web application running at one origin, access to selected resources from 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.

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: <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: <headers>: As the name implies, this lists the headers the browser has access to.
  • Access-Control-Max-Age: <seconds>: This indicates the duration for which the response of a preflight request can be cached.
  • Access-Control-Allow-Credentials: <boolean>: This indicates that the browser can make use of the response when the initial request was made with a credential.
  • Access-Control-Allow-Methods: <methods>: This indicates the method(s) that allowed when attempting to access a resource.
  • Access-Control-Allow-Headers: <headers>: This indicates the HTTP headers can be used in a request.

Here is an example of what the response will look like

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Vary: Access-Control-Request-Headers
Access-Control-Allow-Headers: Content-Type, Accept
Content-Length: 0
Date: Sat, 16 Nov 2019 11:41:08 GMT+1
Connection: keep-alive

Request Headers

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

  • Origin: <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: <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: <header>: 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

curl -i -X OPTIONS localhost:3001/api \
-H 'Access-Control-Request-Method: GET' \
-H 'Access-Control-Request-Headers: Content-Type, Accept' \
-H 'Origin: http://localhost:3000'

Preflight Requests

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

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.

config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins '*'
    resource '*',
       headers: :any,
       expose: %i(access-token expiry token-type uid client),
       methods: %i(get post put patch delete options head),
       credentials: true
  end
end

NodeJS

In Node.js, this will look like this.

app.all(‘*’, (req, res, next) => {
  res.header(‘Access-Control-Allow-Origin’, ‘*’);
  res.header(‘Access-Control-Allow-Methods’, ‘PUT, GET, POST, DELETE, PATCH, OPTIONS HEAD’);
  res.header(‘Access-Control-Allow-Headers’, ‘*’);
  res.header(‘Access-Control-Allow-Credentials’, true);
  next();
});

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. You may also checkout Sqreen who provides a security headers module to be integrated with Ruby, PHP, Python, Java, Go, Node.JS applications. 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.