close
close

How CORS actually works behind the scenes

How CORS actually works behind the scenes

Cross-Origin Resource Sharing (CORS) is a critical security mechanism implemented by web browsers to protect users from potentially malicious scripts. However, it is also a common source of frustration for developers, especially those new to web development. This article aims to demystify CORS, explain why it exists, and provide strategies for dealing with CORS-related issues.

What is CORS?

CORS is a security feature implemented by web browsers that controls access to resources (such as APIs or fonts) on a web page from another domain outside of the domain where the resource originated.

Same Origin Policy

To understand CORS, we must first understand the Same Origin Policy. This policy is a fundamental security measure in web browsers that limits how a document or script loaded from one origin can interact with resources from another origin. An origin is defined by the combination of protocol, domain, and port.

For example:

  • https://example.com/page1 And https://example.com/page2 have the same origin.
  • https://example.com And http://example.com have different origins (different protocol).
  • https://example.com And https://api.example.com have different origins (different subdomain).

Why does CORS exist?

CORS was introduced to allow servers to specify which origins are allowed to access their resources, thus relaxing the same-origin policy in a controlled manner. This is crucial for modern web applications that often need to make requests to APIs hosted on different domains.

Common CORS Errors

Developers often encounter CORS errors when trying to make requests from a web application to an API on another domain. A typical CORS error might look like this:

Access to fetch at 'https://api.example.com/data' from origin 'https://myapp.com' 
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present 
on the requested resource.
Enter full screen mode

Exit full screen mode

How CORS works

When a web application makes a cross-origin request:

  1. The browser sends the request with a Origin header specifying the origin of the requesting page.
  2. The server can then respond with:
    • A Access-Control-Allow-Origin header specifying which origins are allowed.
    • Other CORS headers controlling allowed methods, headers, etc.
  3. If the server response does not include the appropriate CORS headers, the browser blocks the response.

Troubleshooting CORS Issues

1. Server-side configuration

The best way to resolve CORS issues is to configure the server to send the correct CORS headers. This typically involves:

  • Setting the Access-Control-Allow-Origin header to specify allowed origins.
  • Configure other CORS headers as needed (e.g., Access-Control-Allow-Methods, Access-Control-Allow-Headers).

Example in Node.js with Express:

const express = require('express');
const cors = require('cors');
const app = express();

app.use(cors({
  origin: 'https://myapp.com'
}));

// Your routes here
Enter full screen mode

Exit full screen mode

2. Using a proxy

If you don’t have control over the server, you can set up a proxy server that adds the necessary CORS headers. This is often done in development environments.

Example of using Create React App’s proxy functionality:

In package.json:

{
  "proxy": "https://api.example.com"
}
Enter full screen mode

Exit full screen mode

3. JSONP (for GET requests only)

JSONP (JSON with Padding) is an older technique that can bypass CORS for GET requests by using script tags, which are not subject to the Same Origin Policy.

function handleResponse(data) {
  console.log(data);
}

const script = document.createElement('script');
script.src = 'https://api.example.com/data?callback=handleResponse';
document.body.appendChild(script);
Enter full screen mode

Exit full screen mode

Note: JSONP is considered deprecated and less secure than a proper CORS implementation.

Good practices

  1. Understanding the security implications:Don’t blindly bypass CORS. It exists for a reason.
  2. Use specific origins:Avoid using * In Access-Control-Allow-Origin in production. Specify the exact origins authorized.
  3. Use environment-specific configurations:Have different CORS settings for development and production environments.
  4. Manage prior review requests:For non-simple requests, handle OPTIONS requests correctly.
  5. Keep safety in mind:Remember that CORS is enforced by the browser. Server-side security measures are still required.

Conclusion

Although CORS can be frustrating, it is an important security feature. By understanding how it works and implementing appropriate solutions, developers can create secure and functional web applications that interact with resources across different domains.

Remember, if you’re having issues with CORS, the first step is to determine if you have control of the server. If so, the best solution is to implement proper CORS headers. Otherwise, consider using a proxy or, as a last resort for simple GET requests, JSONP.