Skip to content
cybersecurity web-security

CORS (CORS)

cors web-security http-headers browser-security
Plain English

CORS is a security rule that browsers enforce. By default, a web page on one website cannot make requests to a different website’s API (this prevents malicious sites from stealing your data). CORS is the mechanism that lets servers explicitly say “I allow requests from these specific websites.” If you have ever seen a “CORS error” in your browser console, it means the server did not give your website permission to access it.

Technical Definition

Cross-Origin Resource Sharing (CORS) is a browser-enforced mechanism (W3C specification) that uses HTTP headers to allow or deny cross-origin requests. The Same-Origin Policy (SOP) blocks requests between different origins by default; CORS provides controlled exceptions.

Origin = scheme + hostname + port. https://bytesnation.com and https://api.bytesnation.com are different origins.

CORS flow:

Simple requests (GET, POST with simple headers): browser sends the request with an Origin header. Server responds with Access-Control-Allow-Origin. Browser enforces the policy.

Preflight requests (PUT, DELETE, custom headers, JSON content-type): browser first sends an OPTIONS request to check permissions before sending the actual request.

Key headers:

HeaderDirectionPurpose
Access-Control-Allow-OriginResponseWhich origins are allowed (* or specific domain)
Access-Control-Allow-MethodsResponseAllowed HTTP methods
Access-Control-Allow-HeadersResponseAllowed request headers
Access-Control-Allow-CredentialsResponseWhether cookies/auth headers are allowed
Access-Control-Max-AgeResponseHow long to cache preflight results (seconds)
OriginRequestThe requesting page’s origin

Critical security rule: never use Access-Control-Allow-Origin: * with Access-Control-Allow-Credentials: true. This would allow any website to make authenticated requests to your API.

CORS configuration

// Express.js CORS middleware
import cors from "cors";

app.use(cors({
  origin: ["https://bytesnation.com", "https://www.bytesnation.com"],
  methods: ["GET", "POST", "PUT", "DELETE"],
  allowedHeaders: ["Content-Type", "Authorization"],
  credentials: true,
  maxAge: 86400, // Cache preflight for 24 hours
}));
# Nginx CORS headers
location /api/ {
    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' 'https://bytesnation.com';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE';
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
        add_header 'Access-Control-Max-Age' 86400;
        return 204;
    }
    add_header 'Access-Control-Allow-Origin' 'https://bytesnation.com';
    add_header 'Access-Control-Allow-Credentials' 'true';
    proxy_pass http://backend;
}
In the Wild

CORS errors are one of the most common frustrations in web development. Every developer building a frontend that calls a separate API backend encounters CORS during development (localhost:3000 calling localhost:8080 is a cross-origin request). The fix is always on the server side: the API must send the correct CORS headers. In production, CORS should be configured to allow only your specific frontend domains, never * for authenticated APIs. CDNs and API gateways (Cloudflare, AWS API Gateway) can handle CORS headers centrally. A common misconfiguration is reflecting the Origin header back as the Access-Control-Allow-Origin value without validation, which effectively disables CORS protection entirely.