Skip to content

Handling CORS (Cross-Origin Resource Sharing)

Cross-Origin Resource Sharing (CORS) is a security mechanism implemented by web browsers to prevent unauthorized access to resources from a different origin. This document provides guidance on understanding and properly handling CORS in web applications.


What is CORS?

CORS is a protocol that allows a web application running on one origin (e.g., https://example.com) to access resources on another origin (e.g., https://api.example.com). Browsers enforce CORS to prevent potential cross-origin attacks, such as CSRF (Cross-Site Request Forgery).

Key Terms
  • Origin: A combination of scheme (protocol), host (domain), and port (e.g., https://example.com:443).
  • Preflight Request: A request sent by the browser to check if the server permits cross-origin requests.

Common Scenarios Requiring CORS

Quote
  • Accessing a third-party API.
  • Communicating between subdomains (e.g., app.example.com and api.example.com).
  • Hosting your frontend and backend on different origins.

How CORS Works

Simple Requests

For simple requests (e.g., GET or POST with specific headers), the browser sends the request directly to the server.

Preflight Requests

For complex requests (e.g., PUT, DELETE, or requests with custom headers), the browser sends a preflight OPTIONS request to the server to determine if the actual request is allowed.

Server Response

The server must respond with appropriate CORS headers, such as:

Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type

Setting Up CORS

Configuring CORS on the Server

CORS headers need to be configured on the server-side to allow cross-origin requests. Below are examples for popular backend frameworks.

Node.js with Express
const cors = require("cors");
const express = require("express");
const app = express();

const corsOptions = {
    origin: "https://example.com",
    methods: ["GET", "POST", "PUT", "DELETE"],
    allowedHeaders: ["Content-Type", "Authorization"],
};

app.use(cors(corsOptions));

app.get("/api", (req, res) => {
    res.json({ message: "CORS is configured!" });
});

app.listen(3000, () => console.log("Server running on port 3000"));
Python with Flask
from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app, resources={r"/*": {"origins": "https://example.com"}})

@app.route("/api")
def api():
    return {"message": "CORS is configured!"}

if __name__ == "__main__":
    app.run()
Django

Install and configure the django-cors-headers package:

pip install django-cors-headers

Add to your settings.py:

INSTALLED_APPS += [
    'corsheaders',
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    *MIDDLEWARE,
]

CORS_ALLOWED_ORIGINS = [
    'https://example.com',
]

Using Proxy Servers

If you cannot modify the server, set up a proxy to handle CORS. For example, configure a proxy in a React app:

vite.config.js
import { defineConfig } from "vite";

export default defineConfig({
  server: {
    proxy: {
      "/api": {
        target: "https://api.example.com",
        changeOrigin: true,
      },
    },
  },
});

Debugging CORS Issues

Common Errors

  • No 'Access-Control-Allow-Origin' header: The server did not respond with a valid CORS header.
  • CORS preflight request failed: The server did not respond to the preflight OPTIONS request.

Tools for Debugging

  • Use browser developer tools to inspect network requests and responses.
  • Check the server logs for CORS-related errors.

Checklist

  • Verify the server includes the correct Access-Control-Allow-Origin header.
  • Ensure preflight requests are handled correctly on the server.
  • Confirm that the browser and server are communicating over HTTPS.

Security Considerations

Restrict Allowed Origins

  • Avoid using * as the value for Access-Control-Allow-Origin in production.

  • Specify exact origins:

    Access-Control-Allow-Origin: https://example.com
    

Validate Tokens

  • Use proper authentication mechanisms (e.g., JWTs) to validate API requests.

Limit Methods and Headers

  • Restrict Access-Control-Allow-Methods and Access-Control-Allow-Headers to only what is necessary.

Rate Limiting

  • Implement rate limiting to prevent abuse of your API.

By correctly setting up and managing CORS, you can securely enable cross-origin communication while protecting your application from potential threats.