Table of contents
1.
Introduction
2.
What is CORS?
2.1.
Key Features of CORS
3.
How CORS Works?
3.1.
1. Simple Requests
3.2.
2. Preflight Requests
4.
Why Use CORS?
5.
Steps to Implement/Enable CORS in Node.js App
5.1.
Prerequisites
5.2.
Step 1: Install the cors Package
5.3.
Step 2: Require and Use the cors Middleware
5.4.
Step 3: Restrict CORS to Specific Origins
5.5.
Step 4: Test Your Application
6.
Enable All CORS Requests  
6.1.
Enable CORS for a Single Route  
7.
Configure CORS with Options  
8.
Configuring Dynamic CORS Origins Using a Function  
9.
Loading List of Allowed Origins from a Data Source  
10.
Inside the Server Directory
10.1.
Organizing CORS Logic in Middleware
10.2.
Applying Middleware in Your Server
11.
Frequently Asked Questions
11.1.
What happens if CORS is not enabled?
11.2.
Can I allow all origins in CORS?
11.3.
How do I debug CORS errors?
12.
Conclusion
Last Updated: Jan 18, 2025
Medium

CORS in Node.js

Author Pallavi singh
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

CORS in Node.js (Cross-Origin Resource Sharing) is a security feature that allows web applications running at one origin (domain) to make requests for resources from a different origin. It is commonly used when building APIs or web services that need to be accessed from different domains or front-end applications. By enabling CORS, you control which websites or apps can interact with your server.

CORS in Node.js

In this article, we will discuss what CORS is, how it works, and how to implement it in a Node.js application using practical examples.

What is CORS?

CORS stands for Cross-Origin Resource Sharing. It is a security feature implemented by web browsers to prevent unauthorized access to resources from different origins. By default, browsers restrict requests made from one origin to another due to the same-origin policy. CORS allows servers to explicitly grant permission to specified origins for accessing their resources.

Key Features of CORS

  • Cross-Origin Requests: Allows sharing of resources between different domains.
     
  • Preflight Requests: Ensures proper authorization before processing sensitive operations.
     
  • Security: Protects web applications from malicious cross-origin requests.
     

For example, if your front-end application (hosted on http://localhost:3000) wants to fetch data from an API hosted on http://api.example.com, you need to enable CORS on the API server to allow this interaction.

How CORS Works?

CORS works by using HTTP headers to specify which origins are allowed to access a server’s resources. The process includes two types of requests:

1. Simple Requests

These are basic HTTP requests (e.g., GET or POST) where the browser directly sends the request with an Origin header. If the server allows the origin, it includes the appropriate CORS headers in its response.

Example:

Request:

GET /data HTTP/1.1

Host: api.example.com

  • Origin: http://localhost:3000

Response:

HTTP/1.1 200 OK
  • Access-Control-Allow-Origin: http://localhost:3000

2. Preflight Requests

For complex requests (e.g., PUT, DELETE), the browser sends an additional OPTIONS request to check if the server allows the operation before making the actual request.

Preflight Request:

OPTIONS /data HTTP/1.1

Host: api.example.com

Origin: http://localhost:3000

Access-Control-Request-Method: DELETE

Server Response:

HTTP/1.1 204 No Content

Access-Control-Allow-Origin: http://localhost:3000

Access-Control-Allow-Methods: GET, POST, PUT, DELETE

Access-Control-Allow-Headers: Content-Type

Why Use CORS?

CORS is essential for modern web applications that rely on APIs hosted on different domains. Here are the main reasons to use CORS:

  1. Enable Cross-Domain Communication: CORS allows a front-end application to interact with a back-end server hosted on a different domain, enabling seamless integration between services.
     
  2. Improve Security: It prevents unauthorized access to resources by explicitly specifying which origins are allowed.
     
  3. Enhance User Experience: By enabling CORS, users can interact with APIs without being restricted by browser policies.
     
  4. Compliance with Modern Web Standards: CORS ensures compatibility with single-page applications (SPAs) and other web technologies.

Steps to Implement/Enable CORS in Node.js App

Enabling CORS in a Node.js application is quite simple with the help of the cors middleware.

Prerequisites

  • Node.js installed
     
  • A basic Express application

Step 1: Install the cors Package

Run the following command to install the cors middleware:

npm install cors

Step 2: Require and Use the cors Middleware

Here’s how you can enable CORS in your Express application:

Example

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

// Enable CORS for all routes
app.use(cors());

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

app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});

Step 3: Restrict CORS to Specific Origins

To allow specific origins, pass an options object to the cors middleware:

Example:

const corsOptions = {
    origin: 'http://localhost:3000', // Allow only this origin
    methods: ['GET', 'POST'], // Allow specific HTTP methods
    allowedHeaders: ['Content-Type'], // Allow specific headers
};
app.use(cors(corsOptions));

Step 4: Test Your Application

Start your server and make a request from a front-end application or Postman. If CORS is configured correctly, the server will respond without any errors.

Enable All CORS Requests  

Enabling CORS for all requests is the simplest way to allow cross-origin resource sharing in your Node.js application. This is useful when you want to allow any domain to access your API or server resources. To achieve this, you can use the `cors` middleware package in Node.js.  

First, you need to install the `cors` package. Open your terminal & run the following command:  

npm install cors


Once the package is installed, you can enable CORS for all requests by adding the middleware to your Node.js application. Let’s see how you can do it:  

const express = require('express');
const cors = require('cors');
const app = express();
// Enable CORS for all routes
app.use(cors());
app.get('/', (req, res) => {
  res.send('CORS is enabled for all routes!');
});
const PORT = 3000;
app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});


In this example:  

1. We import the `express` & `cors` packages.  
 

2. We create an Express app & use the `cors()` middleware to enable CORS for all routes.
  

3. A simple route (`/`) is defined to test the setup.  
 

4. The server listens on port 3000.  


With this setup, any domain can make requests to your server without running into CORS errors. However, this approach is not recommended for production environments because it allows all domains to access your resources, which can be a security risk.  

Enable CORS for a Single Route  

Enabling CORS for a single route is a more controlled approach compared to enabling it for all requests. This is useful when you want to restrict cross-origin access to specific endpoints in your Node.js application. For example, you might want to allow CORS only for an API route while keeping other routes restricted.  

To enable CORS for a single route, you can apply the `cors()` middleware directly to that specific route. Let’s see how you can do it:  

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

// Enable CORS only for the /api route
app.get('/api', cors(), (req, res) => {
  res.json({ message: 'CORS is enabled for this route!' });
});

// This route will not have CORS enabled
app.get('/no-cors', (req, res) => {
  res.send('CORS is not enabled for this route!');
});

const PORT = 3000;
app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});


In this example:  

1. We import the `express` & `cors` packages.  
 

2. We apply the `cors()` middleware only to the `/api` route. This means that only requests to `/api` will have CORS enabled.  
 

3. The `/no-cors` route does not have CORS enabled, so requests to this route from a different origin will be blocked by the browser.  
 

4. The server listens on port 3000.  


This approach gives you more control over which routes are accessible from different origins. It’s a good practice to enable CORS only for the routes that need it, reducing the risk of unauthorized access to other parts of your application.  

Configure CORS with Options  

Configuring CORS with options allows you to customize how cross-origin requests are handled in your Node.js application. For example, you can specify which HTTP methods are allowed, which headers can be sent, or which domains are permitted to access your resources. This is particularly useful when you want to tighten security & control access to your API.  

To configure CORS with options, you can pass an options object to the `cors()` middleware. For example:  

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

// CORS options
const corsOptions = {
  origin: 'https://example.com', // Allow only this domain
  methods: 'GET,POST', // Allow only GET and POST requests
  allowedHeaders: 'Content-Type,Authorization', // Allow only specific headers
  optionsSuccessStatus: 200 // Some legacy browsers choke on 204
};

// Enable CORS with options for the /api route
app.get('/api', cors(corsOptions), (req, res) => {
  res.json({ message: 'CORS is configured with options for this route!' });
});

const PORT = 3000;
app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});


In this example:  

1. We define a `corsOptions` object to customize the CORS behavior:  

   - `origin`: Specifies which domain is allowed to access the resource. Only requests from `https://example.com` will be permitted.  

   - `methods`: Specifies which HTTP methods are allowed. Here, only `GET` & `POST` requests are allowed.  

   - `allowedHeaders`: Specifies which headers can be included in the request. Only `Content-Type` & `Authorization` headers are allowed.  

   - `optionsSuccessStatus`: Sets the HTTP status code for successful `OPTIONS` requests. Some older browsers may not handle a `204` status code correctly, so we set it to `200`.  


2. We apply the `cors(corsOptions)` middleware to the `/api` route. This ensures that the CORS configuration is applied only to this route.  


3. The server listens on port 3000.  


This approach gives you fine-grained control over how cross-origin requests are handled. You can adjust the options based on your application’s requirements & security needs.  

Configuring Dynamic CORS Origins Using a Function  

Sometimes, you may want to allow multiple domains to access your resources dynamically. For example, you might have a list of trusted domains, & you want to check if the incoming request’s origin is in that list. This is where configuring CORS with a dynamic origin function becomes useful.  

To achieve this, you can pass a function to the `origin` property in the CORS options. This function will check the request’s origin & decide whether to allow or deny the request. Let’s see how you can do it:  

const express = require('express');
const cors = require('cors');
const app = express();
// List of allowed origins
const allowedOrigins = [
  'https://example.com',
  'https://another-example.com',
  'http://localhost:3000'
];
// CORS options with a dynamic origin function
const corsOptions = {
  origin: (origin, callback) => {
    // Check if the origin is in the allowed list
    if (allowedOrigins.includes(origin)) {
      callback(null, true); // Allow the request
    } else {
      callback(new Error('Not allowed by CORS')); // Deny the request
    }
  },
  methods: 'GET,POST', // Allow only GET and POST requests
  allowedHeaders: 'Content-Type,Authorization', // Allow only specific headers
  optionsSuccessStatus: 200 // Set the status code for OPTIONS requests
};
// Enable CORS with dynamic origin for the /api route
app.get('/api', cors(corsOptions), (req, res) => {
  res.json({ message: 'CORS is configured with dynamic origins for this route!' });
});
const PORT = 3000;
app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});


In this example:  

1. We define a list of allowed origins (`allowedOrigins`) that includes the domains you want to permit.  
 

2. We create a `corsOptions` object & pass a function to the `origin` property. This function takes two parameters:  
 

   - `origin`: The origin of the incoming request.  

   - `callback`: A function to call with the result of the check. It takes two arguments: an error (if any) & a boolean indicating whether the origin is allowed.  

 

3. Inside the function, we check if the request’s origin is in the `allowedOrigins` list. If it is, we call `callback(null, true)` to allow the request. If not, we call `callback(new Error('Not allowed by CORS'))` to deny the request. 
 

4. We apply the `cors(corsOptions)` middleware to the `/api` route.  
 

5. The server listens on port 3000.  
 

This approach is flexible & allows you to dynamically control which domains can access your resources. It’s particularly useful when you have a growing list of trusted domains or need to handle requests from multiple environments (e.g., development, staging, production).  

Loading List of Allowed Origins from a Data Source  

In real-world applications, you might want to load the list of allowed origins from a data source like a database or a configuration file. This approach is useful when the list of allowed domains is large or frequently updated. By fetching the allowed origins dynamically, you can keep your CORS configuration flexible & maintainable.  

Let’s take an example of how to load allowed origins from a JSON file & configure CORS dynamically:  


Step 1: Create a JSON file (`allowedOrigins.json`)  

Create a file named `allowedOrigins.json` in your project directory & add the list of allowed origins:  

[
  "https://example.com",
  "https://another-example.com",
  "http://localhost:3000"
]


Step 2: Load the allowed origins & configure CORS  

Now, update your Node.js application to load the allowed origins from the JSON file & configure CORS dynamically:  

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

// Load allowed origins from the JSON file
const allowedOrigins = JSON.parse(fs.readFileSync('allowedOrigins.json', 'utf-8'));

// CORS options with a dynamic origin function
const corsOptions = {
  origin: (origin, callback) => {
    // Check if the origin is in the allowed list
    if (allowedOrigins.includes(origin)) {
      callback(null, true); // Allow the request
    } else {
      callback(new Error('Not allowed by CORS')); // Deny the request
    }
  },
  methods: 'GET,POST', // Allow only GET and POST requests
  allowedHeaders: 'Content-Type,Authorization', // Allow only specific headers
  optionsSuccessStatus: 200 // Set the status code for OPTIONS requests
};


// Enable CORS with dynamic origin for the /api route
app.get('/api', cors(corsOptions), (req, res) => {
  res.json({ message: 'CORS is configured with dynamically loaded origins for this route!' });
});


const PORT = 3000;
app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});


In this example:  

1. We use the `fs` module to read the `allowedOrigins.json` file & parse it into an array of allowed origins.  
 

2. We define the `corsOptions` object & pass a function to the `origin` property. This function checks if the request’s origin is in the `allowedOrigins` array.  
 

3. If the origin is allowed, the request is permitted. Otherwise, an error is thrown.  
 

4. We apply the `cors(corsOptions)` middleware to the `/api` route.  
 

5. The server listens on port 3000.  


This approach makes it easy to manage & update the list of allowed origins without modifying your code. You can extend this further by loading the list from a database or an external API.  

Inside the Server Directory

When implementing CORS in a real-world application, organize your project structure for maintainability:

Example Directory Structure

project-directory
├── server.js
├── routes/
│   ├── apiRoutes.js
├── middleware/
    └── corsMiddleware.js

Organizing CORS Logic in Middleware

Create a corsMiddleware.js file to centralize your CORS configuration:

Example:

const cors = require('cors');
const corsOptions = {
    origin: ['http://localhost:3000', 'http://example.com'],
    methods: ['GET', 'POST', 'PUT', 'DELETE'],
    allowedHeaders: ['Content-Type', 'Authorization'],
};
module.exports = cors(corsOptions);

Applying Middleware in Your Server

Use the custom middleware in your server file:

Example:

const express = require('express');
const corsMiddleware = require('./middleware/corsMiddleware');
const app = express();
const PORT = 5000;
app.use(corsMiddleware);

app.get('/data', (req, res) => {
    res.json({ message: 'Custom CORS middleware is working!' });
});
app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});

Frequently Asked Questions

What happens if CORS is not enabled?

If CORS is not enabled, browsers will block requests from other origins due to the same-origin policy, leading to errors in client-side applications.

Can I allow all origins in CORS?

Yes, you can allow all origins by using app.use(cors()). However, it is not recommended for production environments as it poses security risks.

How do I debug CORS errors?

Use browser developer tools to inspect the network requests. Look for CORS-related headers like Access-Control-Allow-Origin and ensure they are configured correctly on the server.

Conclusion

In this article, we discussed what CORS is, how it works, and why it is crucial for web applications. We also learned how to enable CORS in a Node.js application using the cors middleware and organize your project effectively. By implementing CORS, you can ensure secure and seamless communication between your applications.

You can also check out our other blogs on Code360.

Live masterclass