Implementing CORS in JavaScript Web Applications

Broswers enforce the same-origin policy as a security measure, restricting web pages from making requests to a different origin (scheme, host, or port). This restriction often blocks legitimate cross-origin data access, which is where Cross-Origin Resource Sharing (CORS) comes into play. CORS is a mechanism that allows servers to explicitly whitelist certain origins, methods, and headers, enabling secure cross-origin communication.

Core CORS Headers

CORS relies on specific HTTP response headers:

  • Access-Control-Allow-Origin – defines permitted origins. Use a specific origin (e.g., https://example.com) or * to allow all origins.
  • Access-Control-Allow-Methods – lists allowed HTTP methods (e.g., GET, POST, PUT).
  • Access-Control-Allow-Headers – indicates which request headers can be used (e.g., Content-Type, Authorization).
  • Access-Control-Allow-Credentials – if true, the browser includes credentials (cookies, authorization headers) in the request.
  • Access-Control-Expose-Headers – specifies which response headers are accessible to client scripts.

Setting Up CORS on the Server (Node.js with Express)

Below is an Express middleware that attaches the necessary CORS headers:

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

app.use((req, res, next) => {
  // Allow all origins (for development only; restrict in production)
  res.setHeader('Access-Control-Allow-Origin', '*');
  // Specify allowed methods
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
  // Specify allowed headers
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  // Enable credentials if needed
  // res.setHeader('Access-Control-Allow-Credentials', 'true');

  // Handle preflight requests
  if (req.method === 'OPTIONS') {
    return res.status(200).end();
  }

  next();
});

app.get('/api/data', (req, res) => {
  res.json({ message: 'Cross-origin response works!' });
});

app.listen(4000, () => {
  console.log('Server listening on port 4000');
});

Making CORS Requests from the Client

Using fetch with credentials:

const endpoint = 'http://localhost:4000/api/data';

fetch(endpoint, {
  method: 'GET',
  credentials: 'include',           // sends cookies with the request
})
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  })
  .then(data => console.log('Data:', data))
  .catch(err => console.error('Fetch error:', err));

Using XMLHttpRequest:

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:4000/api/data', true);
xhr.withCredentials = true;  // required when Access-Control-Allow-Credentials is true
xhr.onload = function () {
  if (xhr.status === 200) {
    console.log('Response:', JSON.parse(xhr.responseText));
  }
};
xhr.send();

Handling Preflight Requests

When a request uses a method other than simple methods (GET, HEAD, POST) or includes custom headers, the browser first sends an OPTIONS (preflight) request. The server must respond appropriately:

app.options('/api/data', (req, res) => {
  res.setHeader('Access-Control-Allow-Origin', 'https://yourdomain.com');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Custom-Header');
  res.status(204).end();
});

Common Pitfalls

  • Credentials mismatch: If Access-Control-Allow-Credentials is true, Access-Control-Allow-Origin cannot be *; it must specify an explicit origin.
  • Missing preflight handler: Ensure your server responds to OPTIONS requests with the appropriate CORS headers.
  • Overly permissive origins: Avoid using * in production; specify exact domains to reduce security risks.

CORS provides a controlled way to relax the same-origin policy while maintaining security. By configuring the correct headers and handling preflight requests, developers can integrate cross-origin data flows seamlessyl into their applications.

Tags: cors Cross-Origin Resource Sharing javascript Node.js Express

Posted on Mon, 11 May 2026 09:08:23 +0000 by phpPunk