Adding CORS Headers to Avoid CORS Issues (with Express.js)

🌐 Introduction

Cross-Origin Resource Sharing (CORS) is a browser security mechanism that controls whether a web application can access resources from a different origin. An origin consists of the protocol, domain, and port. Express.js applications often need to configure CORS so that frontend applications running on different origins can communicate with the backend securely.

Information

Browsers enforce CORS policies. Server-to-server requests are generally not restricted by CORS because the policy is implemented by web browsers.

🤔 What is CORS?

When a web application sends a request to a server hosted on a different origin, the browser first checks whether the server allows the request. If the required CORS headers are missing or incorrect, the browser blocks the response and displays a CORS error.

Frontend OriginBackend OriginCORS Required?
http://localhost:3000http://localhost:3000❌ No
http://localhost:3000http://localhost:5000✅ Yes
https://example.comhttps://api.example.com✅ Yes

🔄 How CORS Works

Browser
HTTP Request
Browser Allows or Blocks Response
Express Server
Checks CORS Policy
Sends CORS Headers

âš ī¸ Common CORS Error

If CORS is not configured correctly, the browser may display an error similar to the following:

Typical Browser Error

Access to fetch at 'http://localhost:5000'
from origin 'http://localhost:3000'
has been blocked by CORS policy.

đŸ“Ļ Installing the CORS Package

Express.js provides excellent support for CORS through the cors middleware package.

Install CORS Middleware

npm install cors

📝 Enabling CORS for All Origins

Import the middleware and register it before defining your routes.

Enable CORS Globally

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

const app = express();

app.use(cors());

app.get('/', (req, res) => {
  res.send('CORS Enabled');
});

app.listen(3000);

Success

With app.use(cors()), Express automatically adds the necessary CORS headers for incoming requests.

đŸŽ¯ Allowing Only Specific Origins

In production, it is generally safer to allow requests only from trusted origins instead of allowing every origin.

Allow a Specific Origin

const cors = require('cors');

app.use(cors({
  origin: 'http://localhost:5173'
}));

🌍 Allowing Multiple Origins

Multiple Allowed Origins

const allowedOrigins = [
  'http://localhost:3000',
  'http://localhost:5173'
];

app.use(cors({
  origin: allowedOrigins
}));

🔐 Configuring Additional CORS Options

CORS Configuration

app.use(cors({
  origin: 'http://localhost:5173',
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true
}));
OptionDescription
originSpecifies the allowed origin(s).
methodsLists permitted HTTP methods.
allowedHeadersDefines permitted request headers.
credentialsAllows cookies and authentication credentials.

âš™ī¸ Adding CORS Headers Manually

Although using the cors package is recommended, you can also add CORS headers manually using middleware.

Manual CORS Headers

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header(
    'Access-Control-Allow-Headers',
    'Origin, X-Requested-With, Content-Type, Accept'
  );
  res.header(
    'Access-Control-Allow-Methods',
    'GET, POST, PUT, DELETE'
  );

  next();
});

Warning

Using Access-Control-Allow-Origin: * is convenient during development but is not recommended for applications handling sensitive or authenticated data.

📌 Handling Preflight Requests

Browsers send an OPTIONS request, known as a preflight request, before certain cross-origin requests to verify that the server permits the operation.

Handle Preflight Requests

app.options('*', cors());

🔄 CORS Request Lifecycle

📊 Common CORS Headers

HeaderPurpose
Access-Control-Allow-OriginSpecifies which origins are allowed.
Access-Control-Allow-MethodsLists allowed HTTP methods.
Access-Control-Allow-HeadersLists permitted request headers.
Access-Control-Allow-CredentialsAllows cookies and credentials.
Access-Control-Max-AgeSpecifies how long preflight responses may be cached.

💡 Best Practices

  • Use the cors middleware instead of manually setting headers whenever possible.
  • Restrict origin to trusted domains in production.
  • Avoid using Access-Control-Allow-Origin: * for authenticated applications.
  • Allow only the HTTP methods and headers your application actually requires.
  • Enable credentials only when cookies or authentication tokens are needed.
  • Test cross-origin requests from your frontend before deploying to production.

Best Practice

For most Express.js applications, using the official cors middleware with a carefully configured list of trusted origins provides a secure and maintainable solution.

📚 Learn More

Explore the official documentation for CORS configuration:
â€ĸ Express.js Official Documentation
â€ĸ Express CORS Middleware
â€ĸ MDN Web Docs - Cross-Origin Resource Sharing (CORS)

📝 Summary

Summary

CORS enables secure communication between applications hosted on different origins. In Express.js, the recommended approach is to use the cors middleware to configure allowed origins, HTTP methods, headers, and credentials. Proper CORS configuration improves security while allowing frontend and backend applications to communicate seamlessly.