CORS (Cross-Origin Resource Sharing)

Understanding cross-origin requests and browser security policies

By Hank Kim

CORS (Cross-Origin Resource Sharing)

Understanding cross-origin requests and browser security policies

CORS (Cross-Origin Resource Sharing)

1. What is CORS?

  • CORS is a mechanism that selectively relaxes the Same-Origin Policy (SOP), a browser security policy that restricts cross-origin requests.
  • Same-Origin Policy (SOP): Only allows a web page to access resources from the same origin (same protocol + domain + port). Any difference counts as a different origin.
  • Since modern apps often separate front-end and back-end servers, CORS allows controlled sharing of resources between different origins via HTTP headers.

CORS high-level flow across origins Figure: Frontend and backend on different origins with CORS headers enabling access.


2. How CORS Works

When a browser makes a cross-origin request, it enforces CORS checks at the client-side (browser) level:

(1) Simple Requests

  • Criteria: GET, HEAD, or POST with simple headers (e.g., Content-Type: application/x-www-form-urlencoded, multipart/form-data, text/plain).
  • Flow:

    1. Browser directly sends the request.
    2. If the server responds with

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

      then the browser allows the response. Otherwise, it blocks it.

(2) Preflight Requests

  • Triggered for non-simple requests (e.g., PUT, DELETE, custom headers, JSON Content-Type).
  • Flow:

    1. Browser automatically sends an OPTIONS request before the actual request.
    2. The server responds with allowed origins, methods, and headers, e.g.:

      Access-Control-Allow-Origin: https://example.com
      Access-Control-Allow-Methods: GET, POST, PUT
      Access-Control-Allow-Headers: Content-Type, Authorization
      
    3. If allowed, the browser sends the actual request. Otherwise, it fails with a CORS error.
  • Preflight responses can be cached by the browser. The cache duration is set with:

    Access-Control-Max-Age: 3600
    

Example of a browser CORS error in the console Figure: Typical browser console error when CORS headers are missing or incorrect.


3. Important Characteristics

  • Not a security enhancement: CORS doesn’t make requests safer. It selectively relaxes SOP to enable cross-origin resource sharing.
  • Browser-only enforcement: CORS is enforced only in browsers. Server-to-server requests (e.g., backend APIs calling each other) are not subject to CORS.
  • CORS errors: Occur when a browser blocks a response due to missing/incorrect CORS headers. The request may succeed at the network level, but the response is inaccessible to JS.

4. Why CORS?

  • With microservices, CDNs, APIs, and separate front-end/back-end deployments, cross-origin requests are essential.
  • CORS provides a standardized way for servers to declare which origins are trusted to access their resources.

5. How to Solve CORS Issues

  1. Server-Side Headers (preferred):

    • Configure the server to include appropriate CORS headers. Example in Express:

      res.setHeader("Access-Control-Allow-Origin", "https://my-frontend.com");
      res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
      res.setHeader(
        "Access-Control-Allow-Headers",
        "Content-Type, Authorization"
      );
      
  2. Proxy Server:

    • If the API server cannot be modified, a proxy can be used.
    • The front-end talks to the proxy (same origin), and the proxy forwards the request to the external API.
    • Since server-to-server requests don’t trigger CORS, this bypasses the restriction.

6. Summary

  • CORS = A browser mechanism to safely allow cross-origin requests by using specific HTTP headers.
  • Flow:

    • Simple requests → direct + check Access-Control-Allow-Origin.
    • Non-simple requests → preflight OPTIONS → server must confirm allowed origin/methods/headers.
  • Key Points:

    • CORS only applies in browsers (not server-to-server).
    • Errors occur due to missing/incorrect headers, not because the request failed.
    • Solutions include proper server-side headers or using a proxy.