DEV Community

Shanu
Shanu

Posted on • Updated on

How CORS actually works behind the scenes

Cross-Origin Resource Sharing (CORS) is a crucial security mechanism implemented by web browsers to protect users from potentially malicious scripts. However, it's 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 (like APIs or fonts) on a web page from another domain outside the domain from which the resource originated.

The Same-Origin Policy

To understand CORS, we first need to understand the Same-Origin Policy. This policy is a fundamental security measure in web browsers that restricts 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 CORS Exists

CORS was introduced to allow servers to specify which origins are allowed to access their resources, thereby 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 a different 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 fullscreen mode Exit fullscreen mode

How CORS Works

When a web application makes a cross-origin request:

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

Resolving CORS Issues

1. Server-side Configuration

The most proper 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.
  • Configuring 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 fullscreen mode Exit fullscreen 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 using Create React App's proxy feature:

In package.json:

{
  "proxy": "https://api.example.com"
}
Enter fullscreen mode Exit fullscreen 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 aren't 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 fullscreen mode Exit fullscreen mode

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

Best Practices

  1. Understand 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 exact allowed origins.
  3. Use environment-specific configurations: Have different CORS settings for development and production environments.
  4. Handle preflight requests: For non-simple requests, handle OPTIONS requests properly.
  5. Keep security in mind: Remember that CORS is enforced by the browser. Server-side security measures are still necessary.

Conclusion

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

Remember, if you're encountering CORS issues, the first step is to determine if you have control over the server. If you do, implementing proper CORS headers is the best solution. If not, consider using a proxy or, as a last resort for simple GET requests, JSONP.

Top comments (7)

Collapse
 
amiteshdn profile image
Amitesh Veeragattam

Good explanation!! An image or GIF depicting the CORS flow might help in better understanding. :)

Collapse
 
peshale_07 profile image
Peshal Bhardwaj

You kept it all short and sweet. Love this

Collapse
 
kwoodgmr profile image
kwood-gmr

Actually if you go the proxy route (assuming it is in the same origin as your web app), that proxy can then forward the request and return the response eliminating the need for CORS altogether.

Collapse
 
akash_deshmukh_0a5782423f profile image
AKASH DESHMUKH

Finds useful ! thanks.

Collapse
 
rtarun3606k profile image
Rtarun3606k

Good explanation

Collapse
 
rafaeljohn9 profile image
JohnKagunda

Thanks for the article, really appreciate it

Collapse
 
axorax profile image
Axorax

nice

Some comments may only be visible to logged-in visitors. Sign in to view all comments.