What is CORS?

Welcome to this introduction to Cross-Origin Resource Sharing (CORS)! Picture a neighborhood block party where each house has a fence. Normally, you can only walk into your own yard, and neighbors need an invitation or a gate code to enter. CORS is like that gate code system: it decides which other “houses” (domains) get to cross your fence (server boundary) and access certain resources.

In this reading, you’ll learn:

After this exploration, you will have a stronger grasp of how to control resource sharing between different domains and why this matters for a secure and functional web application.

Understanding CORS with a Metaphor

Imagine you own a bakery (your server) that produces various pastries (resources like images or APIs). You normally serve customers who walk through your front door (requests from the same domain). However, you might want to let a neighboring coffee shop (a different domain) sell your pastries, but only your croissants and not your signature cupcakes.

CORS provides a way to specify exactly which neighbors (origins) can come in, and which of your pastries (resources) they can buy. Without CORS, it’s like leaving your bakery door open for anyone to come in and grab what they want—even if they shouldn’t be there.

What is CORS?

CORS stands for Cross-Origin Resource Sharing. It allows servers to control which domains (or “origins”) are allowed to make requests and load resources in the browser. An origin is typically a unique combination of protocol (http or https), domain (e.g., example.com), and port (e.g., :3000).

For instance, your server might let https://awesome-app.com request your resources, but deny requests from http://malicious-site.ru. This setup helps you maintain control and security over who can access your data or services.

You can define a custom CORS policy on the server side to be as broad or restrictive as needed. For example:

For deeper insights, the MDN docs on CORS provide extensive details on customizing these rules.

Practical Use Cases for CORS

In real-world apps, CORS is your security guard, preventing unapproved “guests” from walking into your server and helping themselves to your resources. Here are some common scenarios:

These restrictions help limit the surface area for potential attacks, like random domains sending rogue requests or phishing attempts that target your users.

Why CORS?

You might wonder: “Can’t we just check the request’s domain and be sure everything is legit?” Unfortunately, not all browsers and clients play by the same rules. Hackers can forge request headers, making it look as though the request came from anywhere.

Here’s where modern browsers come to the rescue: if a user is on a browser that follows the CORS protocol, the browser itself enforces your CORS policies. So, even if the request’s domain claims to be https://trusted.com, the browser will do an actual check against your server’s Access-Control-Allow-Origin settings. If it doesn’t match, the request is blocked before it can even happen.

This is why CORS is crucial: you rely on a standard protocol that browsers support to verify and limit cross-origin requests.

How Does CORS Work?

Modern browsers use what’s called a preflight request to ask your server if it’s okay to send the real request. This preflight request typically includes:

Your server answers with headers like Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers to indicate who can access what, and how. If the response’s domain (pattern) matches the request’s origin, the browser proceeds with the actual request. If not, the browser stops everything right there.

The key idea: the browser enforces the policy. If the server says “No,” the browser refuses to send the real request. This only applies to browsers supporting CORS, but those are the vast majority of modern browsers.

Step by Step Example (Follow Along Exercise)

Let’s say you have a simple Node.js Express server that wants to allow requests from https://my-cool-app.com. You can install the cors package from npm and configure it as follows:

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

// Define the specific origin allowed
const corsOptions = {
  origin: 'https://my-cool-app.com', // your trusted domain
  methods: ['GET', 'POST'],         // allowed HTTP methods
  allowedHeaders: ['Content-Type']   // allowed headers
};

// Use the cors middleware with your options
app.use(cors(corsOptions));

app.get('/data', (req, res) => {
  res.json({ message: 'CORS is working properly!' });
});

app.listen(4000, () => {
  console.log('Server listening on port 4000');
});
  

In this snippet:

If a request from another origin, such as https://random-site.net, tries to fetch /data, it will fail the preflight check, and the browser won’t allow it.

Real World Examples

CORS comes into play in countless everyday applications:

In each scenario, CORS is the handshake that confirms, “Yes, you are allowed to talk to me about these resources.”

What You Learned

Throughout this reading, you’ve explored:

Ultimately, CORS acts as a gatekeeper for your server’s resources, stepping in to verify the identity and permissions of each new visitor. By setting up proper CORS policies, you reduce the likelihood of unapproved or malicious usage of your data, while still allowing legitimate domains to enjoy what your server has to offer.

In practice, always make your default posture restrictive and add trusted domains as necessary. That way, you’ll build secure, reliable services for your users while keeping the bad actors out.