demo · v141

Migration with Storage Access Headers

For the few sites that genuinely needed the loose site-wide scope (auth for multiple subdomain services from one embed), Chrome ships the Storage Access Headers feature as the migration path. Three steps to opt back in: include header on request, server replies with grant header, browser reattaches cookies for the full grant scope.

checking support…

step 1 ensure storage access is granted in the iframe

The user has clicked "continue" on the Storage Access prompt; document.hasStorageAccess() returns true.

if (!(await document.hasStorageAccess())) {
  await document.requestStorageAccess();
}

step 2 send Sec-Fetch-Storage-Access on the cross-origin request

Browser adds the header automatically when the originating iframe has storage access.

fetch("https://api.foo.com/me", {
  credentials: "include",
  // Browser sets: Sec-Fetch-Storage-Access: active
});

step 3 server responds with Activate-Storage-Access

Marks the server's intent: yes, I expect to share cookies with the originating frame's grant.

HTTP/2 200
Activate-Storage-Access: retry; allowed-origin="https://chat.foo.com"
Set-Cookie: session=xyz; SameSite=None; Secure; Partitioned

// Browser repeats the request with cookies and the server gets a properly-authenticated call.
no simulation yet

full snippet

// Client (inside the embedded chat.foo.com iframe)
async function callApi(url) {
  // Browser adds Sec-Fetch-Storage-Access: active iff the frame has storage access
  const r = await fetch(url, { credentials: "include" });
  return r.json();
}

// Server (api.foo.com)
app.get("/me", (req, res) => {
  if (req.headers["sec-fetch-storage-access"] === "active") {
    res.set("Activate-Storage-Access", 'retry; allowed-origin="https://chat.foo.com"');
  }
  // Then return data — browser will retry with cookies if needed
  res.json({ user: req.user || null });
});

why this angle

The chromestatus entry explicitly names Storage Access Headers as the migration path for sites broken by the strict-SOP change. The handshake has three moving parts — the iframe must already have storage access, the request must announce intent via the new header, and the server must consent via the response header. This concept walks all three so a developer migrating from the loose default has the full pattern in one place.

see also