CORS on ExpressJS

⚠️ Security Warning: Using Access-Control-Allow-Origin: * allows any website to access your resources. Always specify exact origins in production.

Method 1: Using the cors Package (Recommended)

The cors npm package is the standard solution for Express.js CORS handling. It's well-maintained, handles all edge cases, and is used by millions of projects (issue #138).

Installation

npm install cors

Simple Usage - Single Origin

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

// Allow specific origin
app.use(cors({
  origin: 'https://example.com',
  credentials: true
}));

app.get('/api/data', function(req, res) {
  res.json({message: 'CORS enabled'});
});

app.listen(3000);

Multiple Origins with Validation

To allow multiple specific origins (issue #146):

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

const allowedOrigins = ['https://example.com', 'https://app.example.com'];

app.use(cors({
  origin: function (origin, callback) {
    // Allow requests with no origin (mobile apps, curl, etc)
    if (!origin) return callback(null, true);

    if (allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  },
  credentials: true,
  optionsSuccessStatus: 204
}));

app.get('/api/data', function(req, res) {
  res.json({message: 'CORS enabled'});
});

app.listen(3000);

Route-Specific CORS

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

// Public endpoint - open CORS
app.get('/api/public', cors(), function(req, res) {
  res.json({message: 'Public endpoint'});
});

// Private endpoint - restricted CORS
const corsOptions = {
  origin: 'https://example.com',
  credentials: true
};

app.get('/api/private', cors(corsOptions), function(req, res) {
  res.json({message: 'Private endpoint'});
});

app.listen(3000);

Method 2: Manual Implementation (Without Package)

If you prefer not to use a package, implement CORS manually with proper origin validation:

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

// List of allowed origins
const allowedOrigins = [
  'https://example.com',
  'https://app.example.com'
];

// CORS middleware
app.use(function(req, res, next) {
  const origin = req.headers.origin;

  // Validate origin
  if (allowedOrigins.includes(origin)) {
    res.header("Access-Control-Allow-Origin", origin);
    res.header("Vary", "Origin");
    res.header("Access-Control-Allow-Credentials", "true");
  }

  res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");
  res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");

  // Handle preflight
  if (req.method === 'OPTIONS') {
    res.header("Access-Control-Max-Age", "86400");
    return res.sendStatus(204);
  }

  next();
});

// Your routes
app.get('/api/data', function(req, res) {
  res.json({message: 'CORS enabled'});
});

app.post('/api/data', function(req, res) {
  res.json({message: 'POST request'});
});

app.listen(3000, function() {
  console.log('Server running on port 3000');
});

Method 3: Reusable CORS Middleware

Create a reusable middleware module:

// cors-middleware.js
function corsMiddleware(options = {}) {
  const {
    origins = [],
    credentials = true,
    methods = ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
    headers = ['Content-Type', 'Authorization', 'X-Requested-With'],
    maxAge = 86400
  } = options;

  return function(req, res, next) {
    const origin = req.headers.origin;

    // Validate origin
    if (origins.includes(origin)) {
      res.header("Access-Control-Allow-Origin", origin);
      res.header("Vary", "Origin");

      if (credentials) {
        res.header("Access-Control-Allow-Credentials", "true");
      }
    }

    res.header("Access-Control-Allow-Methods", methods.join(", "));
    res.header("Access-Control-Allow-Headers", headers.join(", "));

    // Handle preflight
    if (req.method === 'OPTIONS') {
      res.header("Access-Control-Max-Age", maxAge.toString());
      return res.sendStatus(204);
    }

    next();
  };
}

module.exports = corsMiddleware;

// Usage in app.js
const express = require('express');
const corsMiddleware = require('./cors-middleware');
const app = express();

app.use(corsMiddleware({
  origins: ['https://example.com', 'https://app.example.com'],
  credentials: true
}));

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

app.listen(3000);

Note: The cors package handles preflight requests automatically, validates origins correctly, and handles edge cases you might miss in manual implementations. See the official cors package documentation for more information.

Testing Your CORS Configuration

For comprehensive testing instructions including curl commands, browser DevTools usage, and troubleshooting common CORS errors, see the CORS Testing Guide.

Who’s behind this

Monsur Hossain and Michael Hausenblas

Contribute

The content on this site stays fresh thanks to help from users like you! If you have suggestions or would like to contribute, fork us on GitHub.

Buy the book

Save 39% on CORS in Action with promotional code hossainco at manning.com/hossain