What does the sec-fetch-site header mean? Why is the Origin header undefined?

11,170

I have an API endpoint that I call from my React app. That API is on the same domain. … I was expecting to see an Origin header on my server logs.

Browsers send no Origin in same-origin GET requests, per Fetch spec requirements. ✳️

it's like the Origin check was already made

Yes — browsers know:

  • the origin of the code making the request
  • the origin of the resource for which the request is being made
  • the request method

…and browsers check all those before deciding whether to add the Origin header; and they don’t add the Origin header if the origins match and the method is GET.

// AND I ALSO GET THESE HEADERS
"sec-fetch-dest":"empty",
"sec-fetch-mode":"cors",
"sec-fetch-site":"same-origin"

What do they mean? … For example: if I get sec-fetch-site: cross-site it means that the call was generate in another website/domain? Is that correct?

https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-site-header has details:

Sec-Fetch-Site value What the value indicates
same-origin The origin to which the request is being made matches the origin of the code making the request.
same-site The origin to which the request is being made and the origin of the code making the request have the same “registrable domain” (sometimes also referred to as the “same eTLD+1” or “same effective top-level domain plus one”); so, for example, https://subdomain.example.com and https://example.com are same-site (even though not same-origin).
cross-site The origin to which the request is being made and the origin of the code making the request are neither same-origin nor even same-site but instead have different registrable domains.
none The request wasn’t initiated programatically by frontend code (for example, not by an XHR/fetch/ajax call) but instead initiated by normal user navigation — that is, by a user doing something like directly putting an address into the browser URL bar, or clicking on a hyperlink.

✳️ Spec requirements causing the Origin header to be omitted in same-origin GET requests:

Whether or not the Origin header gets added ultimately depends on the request’s “response tainting”, the value of which starts out as "basic", and which, for same-origin requests, the Fetch algorithm keeps sets to "basic", per step 12 of the “Main fetch” algorithm:

request’s current url’s origin is same origin with request’s origin, and request’s response tainting is "basic"

  1. Set request’s response tainting to "basic".
  2. Return the result of running scheme fetch given fetchParams.

Running scheme fetch causes the append a request `Origin` header algorithm to get invoked, and that causes the Origin header to be added only if at least one of the following is true:

  • the request’s response tainting is "cors"
  • the request’s mode is "websocket"
  • the request’s method is neither GET nor HEAD

But for same-origin GET, the response tainting isn’t cors (rather, per the requirements above, it’s basic), the request mode isn’t websocket, and of course the method isn’t neither GET nor HEAD (it’s GET); thus, the algorithm requires browsers to not add an Origin header.

Share:
11,170
cbdeveloper
Author by

cbdeveloper

I build (React) web apps for a living.

Updated on June 17, 2022

Comments

  • cbdeveloper
    cbdeveloper almost 2 years

    I have an API endpoint that I call from my React app. That API is on the same domain. Something like:

    https://www.example.com
    https://www.example.com/api/update-something
    

    I use cross-fetch to do that request.

    I was expecting to see an Origin header on my server logs. Infact, I was expecting to see Origin: https://www.example.com .

    But here is what I get:

    Origin: undefined
    
    // AND I ALSO GET THESE HEADERS
    
    "sec-fetch-dest":"empty",
    "sec-fetch-mode":"cors",
    "sec-fetch-site":"same-origin"
    

    What do they mean? It's like the Origin check was already made?

    For example: if I get sec-fetch-site: cross-site it means that the call was generate in another website/domain? Is that correct?

    Reference:

    Sec-Fetch-Site: cross-site
    Sec-Fetch-Site: same-origin
    Sec-Fetch-Site: same-site
    Sec-Fetch-Site: none
    
  • cbdeveloper
    cbdeveloper about 3 years
    And the sec-fetch headers are also sent?
  • bottomofeverything
    bottomofeverything about 3 years
    Yes, they are also sent.
  • danludwig
    danludwig about 3 years
    I'm also seeing this behavior for a web app rendered in an iframe (that has same-origin fetch request), but the method is POST instead of GET. Should it also be omitting the origin header when the method is POST?
  • sideshowbarker
    sideshowbarker about 3 years
    @danludwig You may want to consider posting a separate question about that. Without seeing a reproducible example stackoverflow.com/help/minimal-reproducible-example with code and the actual request and response headers, all that anybody here can do is just speculate. But per-spec, a POST request from a fetch call should pretty much always have an Origin header, unless no-cors mode has been set for the request.