Skip to content

Zoom-in: CORS

Karify98·
Cover Image for Zoom-in: CORS

You send an API request from your client app to a server on a different domain, and the browser console instantly flashes a bright red error.

graph LR
    C(["💻 Client\napp.com"]) -->|"API Request"| S(["🖥️ Server\napi.com"])
    S -->|"Response"| C
    style C fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd
    style S fill:#1a3a2a,stroke:#22c55e,color:#86efac

Let's zoom in on that interaction.


Layer 1 — Same-Origin Policy: The Browser's Default Wall

To understand the error, you must first understand the most fundamental web security model: the Same-Origin Policy (SOP).

Under SOP, the browser prevents scripts running on one website from reading sensitive data from another website with a different origin (a different protocol, domain, or port).

Without SOP, a malicious script running on evil.com could fetch data from your bank website (bank.com/api/balance). Because the browser automatically attaches your login cookies when sending requests to bank.com, the attacker could easily read your balance.

Remaining problem: modern web applications need to fetch resources from multiple origins (like CDNs and third-party APIs). They need a safe way to relax SOP.

Layer 2 — Preflight Request: Look Before You Leap

CORS was introduced to relax SOP safely. When a client application performs a non-standard request (such as using PUT, DELETE, or adding custom headers), the browser automatically sends a preliminary request called a Preflight Request.

sequenceDiagram
    participant B as Browser (app.com)
    participant S as Server (api.com)

    B->>S: 1. OPTIONS /data (Preflight)
    S-->>B: 2. 204 No Content (Accept origin app.com)
    B->>S: 3. PUT /data (Real request)
    S-->>B: 4. 200 OK (Result)

The preflight request uses the OPTIONS method. It contains headers describing the actual request that follows, such as Origin and Access-Control-Request-Method.

Its purpose is to ask the server: "I want to send a PUT request from origin app.com, do you support this?". The server checks this and responds with approval or rejection before the browser allows the real data to leave the client.

Remaining problem: even if the server successfully processes the request, the browser must still decide whether to expose the response to the script.

Layer 3 — Browser Enforcement: Handled at Client-Side

A common misconception is that a CORS error means the server blocked the request. In reality, it is the opposite. The server receives, processes, and returns the response normally. The CORS error happens entirely on the client-side when the browser blocks the response.

sequenceDiagram
    participant B as Browser (app.com)
    participant S as Server (api.com)

    B->>S: GET /profile (Request)
    S-->>B: 200 OK + Data (Response without CORS headers)
    Note over B: Detected missing header!<br/>Blocks script from reading Data.

When the server responds, the browser checks for the Access-Control-Allow-Origin header. If the header is missing or does not match the client's origin, the browser blocks the script from reading the returned data and logs an error.

Because of this, you must configure CORS headers on the server. You cannot solve a CORS error by modifying client-side code alone.


Full picture

sequenceDiagram
    participant B as Browser (app.com)
    participant S as Server (api.com)

    alt Simple Request
        B->>S: GET /public-data
        S-->>B: 200 OK + Access-Control-Allow-Origin: *
        Note over B: Valid, exposes data to script
    else Non-Simple Request (Requires Preflight)
        B->>S: OPTIONS /update (Origin: app.com)
        alt Server Approves
            S-->>B: 204 No Content (Access-Control-Allow-Origin: app.com)
            B->>S: PUT /update
            S-->>B: 200 OK + Data
        else Server Rejects
            S-->>B: 400 Bad Request / 204 Denied
            Note over B: Aborts PUT request, logs CORS error
        end
    end

Takeaway

CORS is not a server-side error, nor is it a security tool designed to protect your server from being hit. CORS is a browser-enforced mechanism that protects end-users from data exposure by relaxing the Same-Origin Policy. When you encounter a CORS error, check the headers returned by the destination server rather than looking for a fix in the client app.


This post was assisted by Amy 🌸 - AI Assistant. Content has been reviewed by the author.

Related Posts