Lesson 39 of 50 – CORS in Node.js
78% Completed
78%

CORS in Node.js

Learn how to allow frontend applications to communicate with your Node.js and Express.js APIs using Cross-Origin Resource Sharing (CORS).

What is CORS? CORS stands for Cross-Origin Resource Sharing. It is a browser security mechanism that controls whether a web page can access resources from a different origin.

1. What Is an Origin?

An origin consists of three parts:

  • Protocol – HTTP or HTTPS
  • Domain name – such as example.com
  • Port number – such as 3000 or 5000
Example of Different Origins

Frontend: http://localhost:3000

Backend API: http://localhost:5000

These are different origins because their port numbers are different. A browser request from the frontend to the backend may require CORS permission.

Two URLs can have different origins if their protocol, hostname, or port differs.

2. Why Do We Need CORS?

Suppose you create a React application on port 3000 and an Express API on port 5000. Your frontend tries to fetch student data from the API.

fetch("http://localhost:5000/students")
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error(error));

If the backend does not provide the required CORS headers, the browser may block JavaScript from reading the response.

Important: CORS is enforced by browsers. A CORS error does not necessarily mean your server is offline or your API is broken. Tools such as Postman and server-to-server requests are not restricted by browser CORS enforcement in the same way.

3. Install the CORS Package

Express applications commonly use the cors middleware package to configure CORS headers.

Install Command
npm install cors

Run this command inside your Node.js project directory.

4. Enable CORS in Express.js

The following example allows requests from any origin for this API. Use an appropriate origin policy for your application.

server.js
const express = require("express");
const cors = require("cors");

const app = express();

app.use(cors());

app.get("/", (req, res) => {
    res.send("CORS is enabled!");
});

app.get("/students", (req, res) => {
    res.json([
        { id: 1, name: "Rahul" },
        { id: 2, name: "Priya" }
    ]);
});

app.listen(5000, () => {
    console.log("Server running on port 5000");
});

How Does This Code Work?

  • require("express") imports Express.
  • require("cors") imports the CORS middleware.
  • app.use(cors()) enables the package's default CORS configuration.
  • /students returns a JSON array of students.
  • app.listen(5000) starts the server on port 5000.
Expected result: A frontend running on a different origin can read the API response when the browser's CORS checks are satisfied.

5. Allow a Specific Origin

In production, it is usually better to allow only the frontend origins that need access to your API.

Allow One Frontend
const express = require("express");
const cors = require("cors");

const app = express();

app.use(cors({
    origin: "http://localhost:3000"
}));

app.get("/students", (req, res) => {
    res.json([
        { id: 1, name: "Aman" },
        { id: 2, name: "Neha" }
    ]);
});

app.listen(5000, () => {
    console.log("Server running on port 5000");
});

In this example, the CORS configuration allows the frontend origin http://localhost:3000. Replace it with your actual frontend origin when deploying your application.

6. Allow Multiple Origins

If your application has multiple trusted frontend URLs, you can check the request origin against an allowlist.

const express = require("express");
const cors = require("cors");

const app = express();

const allowedOrigins = [
    "http://localhost:3000",
    "https://soopropathshala.com"
];

app.use(cors({
    origin: function (origin, callback) {
        // Requests without an Origin header may come from
        // tools or server-to-server clients.
        if (!origin || allowedOrigins.includes(origin)) {
            return callback(null, true);
        }

        return callback(new Error("Origin not allowed by CORS"));
    }
}));

app.get("/api", (req, res) => {
    res.json({
        message: "Welcome to the API"
    });
});

app.listen(5000, () => {
    console.log("Server running on port 5000");
});
Security note: Requests without an Origin header are not automatically trustworthy. CORS is not authentication or authorization. Protect private API routes separately.

7. Configure Allowed Methods

You can specify which HTTP methods browser requests may use.

app.use(cors({
    origin: "http://localhost:3000",
    methods: ["GET", "POST", "PUT", "DELETE"]
}));

The configuration above lists the permitted methods for CORS requests. Your Express routes must still implement the corresponding operations.

8. Configure Allowed Headers

Sometimes the frontend sends custom headers, such as an authorization token. You can configure which request headers the browser may use.

app.use(cors({
    origin: "http://localhost:3000",
    methods: ["GET", "POST", "PUT", "DELETE"],
    allowedHeaders: ["Content-Type", "Authorization"]
}));

For example, a frontend can send a JSON request with an authorization header:

fetch("http://localhost:5000/students", {
    method: "GET",
    headers: {
        "Authorization": "Bearer YOUR_TOKEN"
    }
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));

9. What Is a Preflight Request?

Before some cross-origin requests, the browser sends an HTTP OPTIONS request to check whether the actual request is allowed. This is called a preflight request.

Example Request Flow
  1. The frontend wants to send a cross-origin request.
  2. The browser sends an OPTIONS preflight request when required.
  3. The server responds with suitable CORS headers.
  4. If the checks pass, the browser sends the actual request.

Requests using certain methods, custom headers, or content types may trigger preflight checks. A simple GET request does not always require preflight.

When the CORS middleware is correctly installed before your routes, it can handle the preflight requests for those routes.

10. Allow Credentials

If a frontend needs to send cookies or other browser credentials, the server and client must be configured accordingly.

app.use(cors({
    origin: "http://localhost:3000",
    credentials: true
}));

On the frontend, a fetch request can include credentials:

fetch("http://localhost:5000/profile", {
    method: "GET",
    credentials: "include"
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
Important: When credentials are enabled, do not use origin: "*". Configure a specific trusted origin instead. CORS settings do not replace secure cookie settings, authentication, authorization, or CSRF protection where applicable.

11. Common CORS Problems

Problem Possible Solution
CORS error in browser Check the response headers and configure the required origin.
Wrong frontend origin Check the protocol, hostname, and port carefully.
OPTIONS request fails Check middleware order, server handling, and preflight headers.
Custom header is rejected Configure the required header in allowedHeaders.
Credentials are not working Use a specific allowed origin and configure credentials on both sides.
API does not respond Check the server, URL, port, network, and route separately.

12. Test Your CORS Configuration

Follow these steps to test your Express API:

  1. Install Express and the CORS package.
  2. Configure CORS before defining your routes.
  3. Start the API server on port 5000.
  4. Create or open a frontend on port 3000.
  5. Call the API using fetch().
  6. Open browser Developer Tools and check the Console and Network tabs.
  7. Inspect the request and response headers if the browser reports a CORS error.
Remember: Postman can help you test the API itself, but a successful Postman request does not prove that the browser's CORS checks will pass.

13. Practical Assignment

Practice Task

Create a Node.js application with the following requirements:

  1. Create an Express server on port 5000.
  2. Install and configure the cors package.
  3. Create a GET route named /courses.
  4. Return at least three courses as a JSON array.
  5. Allow requests from http://localhost:3000.
  6. Test the route from a frontend running on port 3000.
  7. Check the browser console and network requests.

Bonus: Add a POST route and configure the required request headers.


Test Your Knowledge – CORS

Select the correct answer for each question.

1. What does CORS stand for?
2. Which package is commonly used to configure CORS in Express?
3. Which HTTP method is commonly used for a CORS preflight request?