Back to Blog
Lesson 35 of the Node.js: Build Your First Server & CLI course
Node.jsAugust 23, 20264 min read

CORS Configuration: Secure Your API with Express Middleware

Learn how to configure CORS in Express to allow your frontend to communicate with your API, handle preflight requests, and keep your application secure.

Node.jsExpressCORSAPISecurityMiddleware
Steel framework cabinets housing servers networking devices and cables in contemporary equipped data center

Previously in this course, we discussed adding logging to your API to track request activity. Now that we can monitor our traffic, we need to address a common "gotcha" for new backend developers: the browser's security mechanism that blocks your frontend from calling your API.

Understanding CORS from First Principles

By default, browsers implement the Same-Origin Policy (SOP). This security feature prevents a script on one website (e.g., myapp.com) from making requests to a different domain (e.g., api.myapp.com) unless the server explicitly gives permission.

Cross-Origin Resource Sharing (CORS) is the mechanism that allows servers to "opt-in" to allowing requests from specific origins. Without a proper CORS policy, your browser will block your frontend application from reading the data returned by your API, even if the request technically reaches the server.

Installing and Configuring the CORS Middleware

The most efficient way to manage these headers in an Express application is by using the community-standard cors package.

First, install the package in your project directory:

Bash
npm install cors

Once installed, you need to register it as middleware. In your main server file (usually index.js or app.js), import and use it:

JAVASCRIPT
const express = require(CE9178">'express');
const cors = require(CE9178">'cors');
const app = express();

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

app.get(CE9178">'/api/data', (req, res) => {
  res.json({ message: CE9178">'Hello from the API!' });
});

Using app.use(cors()) without arguments enables CORS for all origins (using the * wildcard). While this works for development, it is not recommended for production.

Restricting Allowed Origins

In a production environment, you should only allow requests from the specific domains that host your frontend. You can configure this by passing an options object to the cors function:

JAVASCRIPT
const corsOptions = {
  origin: CE9178">'https://www.my-frontend-app.com', // Only allow this domain
  methods: [CE9178">'GET', CE9178">'POST'],
  optionsSuccessStatus: 200 
};

app.use(cors(corsOptions));

Handling Preflight Requests

When your frontend makes "non-simple" requests (like those using PUT, DELETE, or custom headers), the browser performs a "preflight" check. It sends an OPTIONS request to your server to ask, "Are you allowed to receive this type of request?"

The cors middleware handles these OPTIONS requests automatically. You don't need to write custom logic to respond to them; simply configuring the middleware correctly ensures that the browser receives the necessary headers (Access-Control-Allow-Origin, Access-Control-Allow-Methods, etc.) to proceed with the actual request.

Request TypeDescriptionHandled by cors?
SimpleGET, POST (standard content types)Yes
PreflightPUT, DELETE, custom headersYes (automatic)

Hands-on Exercise

  1. Open your project and install the cors package.
  2. In your Express app, configure the middleware to only allow requests from http://localhost:3000 (the common default for React/Vue development servers).
  3. Test your API using a simple frontend fetch call from a different port. Verify that the response is successful and that you see the Access-Control-Allow-Origin header in your browser's Network tab.

Common Pitfalls

  • Over-permissiveness: Never use app.use(cors()) in production if you don't have to. Always restrict the origin to your specific frontend URL to prevent unauthorized sites from interacting with your API.
  • Order of Middleware: Always place your app.use(cors()) call before your route definitions. If you place it after, the routes will be processed before the CORS headers are attached, causing the browser to block the response.
  • Ignoring Preflight Errors: If your browser console shows "CORS error" on a DELETE request but not on a GET request, it is likely a preflight failure. Check your server logs to ensure the OPTIONS method isn't being blocked by other custom logic.

For more detailed security considerations, read about preventing improper CORS policy configuration to avoid common vulnerabilities like credential theft.

FAQ

Does CORS protect my API from hackers? No. CORS is a browser-level security feature. It does not stop someone from using tools like Postman or curl to hit your API endpoints. Always use proper authentication and authorization for that.

Why am I still getting a CORS error after adding the middleware? Check your browser console. If the error mentions "Origin not allowed," double-check that your origin configuration matches the frontend URL exactly, including the protocol (http vs https).

Can I allow multiple origins? Yes, you can pass an array of strings to the origin property: origin: ['https://app1.com', 'https://app2.com'].

Recap

We've covered the basics of enabling communication between your frontend and your API. By using the cors middleware, restricting origins to production domains, and letting Express handle preflight OPTIONS requests, you've bridged the gap between your server-side logic and the browser.

Up next: We'll dive into how to process user search queries using URL parameters.

Similar Posts