Skip to content

request.url mismatch when app is loaded in iframe using storage access headers #13622

@mrksbnch

Description

@mrksbnch

I'm using React Router as a...

framework

Reproduction

Go to https://github.com/mrksbnch/react-router-storage-access-headers and follow the steps in the README.md, or refer to the instructions below.
To test this, open the application in Chrome and enable the following flag:
chrome://flags/#test-third-party-cookie-phaseout.

  1. Run npm install to install dependencies.
  2. Run npm run incorrect to start the app at http://localhost:3000 and serve a static iframe.html file located at /public/iframe.html via http://localhost:4000.
  3. Open the iframe at http://localhost:4000.
  4. Grant storage access by clicking the button inside the iframe.
  5. You should see the URL from both window.location.href and request.url (exposed via the loader); these should be identical.
  6. Reload the page.

As background information, this article about Storage Access Headers explains the use cases and how the mechanism works.

The main use case is allowing your app to be loaded inside an iframe.
This typically comes with certain limitations (especially with cookies) which are treated as third-party cookies.
Most browsers already block third-party cookies, and Chrome is following the same path.

There are a few workarounds to these limitations, such as using partitioned cookies or the Storage Access API.
The Storage Access API allows an application to access the same cookies available outside of an iframe (assuming the user has granted access).

In the past, requesting storage access was only possible on the client side, even if the user had already granted access. With Storage Access Headers, it's now possible to request storage access on the server side, assuming that the user has granted access (on the client) once before.

System Info

System:
    OS: macOS 14.6.1
    CPU: (8) arm64 Apple M1
    Memory: 117.17 MB / 8.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 23.7.0 - /opt/homebrew/bin/node
    npm: 10.9.2 - /opt/homebrew/bin/npm
    pnpm: 9.15.0 - ~/Library/pnpm/pnpm
  Browsers:
    Chrome: 136.0.7103.114
    Safari: 17.6
  npmPackages:
    @react-router/dev: ^7.6.0 => 7.6.0 
    @react-router/node: ^7.6.0 => 7.6.0 
    @react-router/serve: ^7.6.0 => 7.6.0 
    react-router: ^7.6.0 => 7.6.0 
    vite: ^6.3.3 => 6.3.5

Used Package Manager

npm

Expected Behavior

The URLs shown in the demo application (window.location.href and request.url (from the loader)) should be the same.

Even when the page is loaded inside an iframe, the server-side URL should not reflect or expose the parent frame’s URL.

Actual Behavior

The URL from the loader (request.url) incorrectly shows the URL of the parent page.
It appears that the React Router dev server sets the URL incorrectly in this case.

Note:

  • The HTTP Host header is correctly set to the actual application’s domain.
  • In the demo, the path is /. If the page was served at a different path, e.g., /page, request.url would still report the hostname of the parent page but show the correct path from the iframe.

I'm not sure if there are any workarounds when using the React Router dev server. It might work correctly with a custom Express server because my Express-based example (linked in the repo) behaves as expected.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions