Intent to Prototype: Extending Storage Access API (SAA) to non-cookie storage

690 views
Skip to first unread message

Ari Chivukula

unread,
Oct 2, 2023, 9:44:05 AM10/2/23
to blink-dev, Ben Kelly, Johann Hofmann, hel...@google.com

Contact emails

ari...@chromium.org, wande...@chromium.org, joha...@chromium.org, hel...@google.com


Specification

https://arichiv.github.io/saa-non-cookie-storage/


Summary

We propose an extension of the Storage Access API (backwards compatible) to allow access to unpartitioned (cookie and non-cookie) storage in a third-party context, and imagine the API mechanics to be roughly like this (JS running in an embedded iframe):


// Request a new storage handle via rSA (this should prompt the user)

let handle = await document.requestStorageAccess({all: true});

// Write some cross-site localstorage

handle.localStorage.setItem("userid", "1234");

// Open or create an indexedDB that is shared with the 1P context

let messageDB = handle.defaultBucket.indexedDB.open("messages");


The same flow would be used by iframes to get a storage handle when their top-level ancestor successfully called rSAFor, just that in this case the storage-access permission was already granted and thus the rSA call would not require a user gesture or show a prompt, allowing for “hidden” iframes accessing storage.


Browsers currently shipping the Storage Access API apply varying methods of when or how to ask the user for permission to grant 3p cookie access to a site. Given that this proposal involves extending the existing Storage Access API, while maintaining largely the same implications (from a privacy/security perspective) to the user, a consistent prompt for cookie and non-cookie access is preferred. No prompt is needed when the origins are RWS (Related Website Sets, the new name for First Party Sets).


Blink component

Blink>Storage


Motivation

There has been increasing developer and implementer interest in first-party DOM Storage and Quota Managed Storage being available in third-party contexts the same way that Cookies already can be. In the absence of such a solution, we would in effect be pushing developers to migrate to Cookies from other storage mechanisms. There are significant tradeoffs between Cookie and non-Cookie storage (size, flexibility, server exposure, network request size, etc.) that could cause a detriment in user experience from a privacy, security and performance perspective. To prevent sub-optimal use of cookies and to preserve context, we propose a solution for developers to regain 3p access to unpartitioned storage in select instances to avoid user-facing breakage in browsers shipping storage partitioning.


TAG review

https://github.com/w3ctag/design-reviews/issues/906


Compatibility

The Storage Access API is already implemented in Safari, Firefox, and Chrome, but the proposed API shape would not change existing behavior without new arguments added.


Interoperability

Gecko: https://github.com/mozilla/standards-positions/issues/898

WebKit: https://github.com/WebKit/standards-positions/issues/262

Web developers: Positive


Debuggability

Storage written can be examined in devtools.


Is this feature fully tested by web-platform-tests?

Tests will be added.


Tracking bug

https://crbug.com/1484966


Link to entry on the Chrome Platform Status

https://chromestatus.com/feature/5175585823522816


Ari Chivukula

unread,
Nov 28, 2023, 4:44:54 PM11/28/23
to Jesper van den Ende, blink-dev, Ben Kelly, Johann Hofmann, hel...@google.com
Thanks for letting us know about your use case. Yes, Chrome has decided not to pursue Shared Worker access via the handle returned by requestStorageAccess given it would allow access to SameSite=Strict cookies to a third-party iframe via that shared worker. We are examining an alternate option where requestStorageAccess will be available in workers: https://github.com/privacycg/storage-access/issues/157

Either way, this change will probably require switching from using a (shared) Shared Worker for tab discovery to something like Broadcast Channel which would allow for cross-tab messaging without the need to be online.

~ Ari Chivukula (Their/There/They're)


On Tue, Nov 28, 2023 at 4:35 PM Jesper van den Ende <jesper...@gmail.com> wrote:
Hi all,

I noticed the TODOs for shared workers were removed.
My application relies on cross origin shared workers and to be honest this was the main part of the proposal I was looking forward to haha.
I'm currently relying on the origin trial for disabling third party storage partitioning.
Are there any plans for the shared worker use case? I'm not sure what to do once the origin trial expires. And as far as I can tell there is no good alternative for what I'm trying to achieve.
Specifically, I'd like to be able to discover other tabs (that are also broadcasting their existence using the same shared worker) and then initiate a connection to them.
One alternative I could think of was using WebRTC for this, but ideally I'd like this to work while the user is offline, which is not possible with WebRTC.

Is there any discussion about the plan to remove shared workers from the proposal? I couldn't find anything about SameSite=Strict cookies anywhere other than the commit that removed the TODOs.

Cheers,
Jesper

Ari Chivukula

unread,
Nov 28, 2023, 6:05:04 PM11/28/23
to Jesper van den Ende, blink-dev, Ben Kelly, Johann Hofmann, hel...@google.com
Testing locally, event.source seems always to be null when using Broadcast Channel. This seems to align with the spec which doesn't mention setting source at all for the MessageEvent: https://html.spec.whatwg.org/multipage/web-messaging.html#broadcasting-to-other-browsing-contexts and the chrome code which doesn't set it: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc;drc=8e78783dc1f7007bad46d657c9f332614e240fd8;l=173

It looks like storing the ArrayBuffer as a Blob (https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL_static) and sharing the resulting URL via BroadcastChannel or other means may work, but I'm unsure about the efficiency of such an approach.

~ Ari Chivukula (Their/There/They're)


On Tue, Nov 28, 2023 at 5:35 PM Jesper van den Ende <jesper...@gmail.com> wrote:
Awesome, thanks for the info!

A broadcast channel doesn't work for my use case unfortunately.
I'd like to create a MessageChannel and then transfer the two MessagePorts to both tabs.
Since a broadcast channel doesn't allow transferring objects, there's no way for me to send messages to both tabs without it also being sent to all other tabs.
And with no way to transfer things such as ArrayBuffers, I reckon this would also be pretty inefficient for some operations.
But maybe I'm missing something? One thing that comes to mind is using the MessageEvent.source to get access to the window of another tab and then send a message to it directly. But I'm not sure if that would work.

Jesper van den Ende

unread,
Nov 28, 2023, 7:18:01 PM11/28/23
to blink-dev, Ari Chivukula, blink-dev, Ben Kelly, Johann Hofmann, hel...@google.com, Jesper van den Ende
Awesome, thanks for the info!

A broadcast channel doesn't work for my use case unfortunately.
I'd like to create a MessageChannel and then transfer the two MessagePorts to both tabs.
Since a broadcast channel doesn't allow transferring objects, there's no way for me to send messages to both tabs without it also being sent to all other tabs.
And with no way to transfer things such as ArrayBuffers, I reckon this would also be pretty inefficient for some operations.
But maybe I'm missing something? One thing that comes to mind is using the MessageEvent.source to get access to the window of another tab and then send a message to it directly. But I'm not sure if that would work.

On Tuesday, November 28, 2023 at 10:44:54 PM UTC+1 Ari Chivukula wrote:

Jesper van den Ende

unread,
Nov 28, 2023, 7:18:08 PM11/28/23
to blink-dev, Ari Chivukula, Ben Kelly, Johann Hofmann, hel...@google.com
Hi all,

I noticed the TODOs for shared workers were removed.
My application relies on cross origin shared workers and to be honest this was the main part of the proposal I was looking forward to haha.
I'm currently relying on the origin trial for disabling third party storage partitioning.
Are there any plans for the shared worker use case? I'm not sure what to do once the origin trial expires. And as far as I can tell there is no good alternative for what I'm trying to achieve.
Specifically, I'd like to be able to discover other tabs (that are also broadcasting their existence using the same shared worker) and then initiate a connection to them.
One alternative I could think of was using WebRTC for this, but ideally I'd like this to work while the user is offline, which is not possible with WebRTC.

Is there any discussion about the plan to remove shared workers from the proposal? I couldn't find anything about SameSite=Strict cookies anywhere other than the commit that removed the TODOs.

Cheers,
Jesper
On Monday, October 2, 2023 at 3:44:05 PM UTC+2 Ari Chivukula wrote:

Jesper van den Ende

unread,
Nov 29, 2023, 6:47:20 PM11/29/23
to blink-dev, Ari Chivukula, blink-dev, Ben Kelly, Johann Hofmann, hel...@google.com, Jesper van den Ende
Ah that's too bad.
I don't think using object urls would be performant. The data in the ArrayBuffer is still accessible after creating the object url, so that does not seem like it is getting transferred.

Is there any chance an api could be exposed in the future that would allow two separate origins to share the same SharedWorker?
Being able to access requestStorageAccess() from within a SharedWorker wouldn't work for my use case, since at that point the two separate workers have already been created.
I need some way to request storage access before creating the SharedWorker.

Maybe I'm misunderstanding the issue of SameSite=Strict cookies being accessible within SharedWorkers, but what if you could only gain access to `handle.SharedWorker` when you requested storageAccess with {all: true}?
Wouldn't that mean you explicitly requested storage access for everything, thus allowing access to any existing SharedWorkers that may have been created?

Ari Chivukula

unread,
Nov 29, 2023, 9:04:02 PM11/29/23
to Jesper van den Ende, blink-dev, Ben Kelly, Johann Hofmann, hel...@google.com
requestStorageAccess currently provides no way to directly control any surfaces with first-party SameSite=Strict cookies. If the handle returned allowed you to access first-party SharedWorkers, those workers would have access to SameSite=Strict cookies. Chrome's decision at this juncture is to not provide that as it would the assurances around what party was making the request the cookies were included in.

Chrome could provide some independent pool of SharedWorkers accessible via requestStorageAccess in a third-party context that did not have access to SameSite=Strict cookies, but where otherwise essentially first-party workers. Chrome could even make these workers accessible from a first-party context via some additional argument (e.g., SharedWorker(..., {enableThirdPartyAccessWithoutSameSiteStrictCookies: true}). That might meet some use cases, but not others. Chrome would want to see more developer interest before considering that.

As for two separate frames on different origins messaging each other, if one frame opens the other in a way that allows access via window.opener, then the two frames can use postMessage cross-origin. Otherwise there isn't a way to message between frames without some sort of extension mediating the process AFAIK.

~ Ari Chivukula (Their/There/They're)

Jesper van den Ende

unread,
Nov 30, 2023, 6:34:31 AM11/30/23
to blink-dev, Ari Chivukula, blink-dev, Ben Kelly, Johann Hofmann, hel...@google.com, Jesper van den Ende
> requestStorageAccess currently provides no way to directly control any surfaces with first-party SameSite=Strict cookies
Ah I see, that makes sense yeah. Thanks for clarifying!

> Chrome would want to see more developer interest before considering that.
That's understandable, I reckon this is probably a super niche use case.
I found one other developer that seemed affected by this (https://crbug.com/1490528), but for all I know they found a different solution for their use case.

I'll try to see if I can get something going with some combination of BroadcastChannel and window.open(). And otherwise I can always fall back to using WebRTC.
Anyway, thanks for the responses!

Jesper van den Ende

unread,
Dec 9, 2023, 6:42:33 PM12/9/23
to blink-dev, Jesper van den Ende, Ari Chivukula, blink-dev, Ben Kelly, Johann Hofmann, hel...@google.com
Hey, I got a small update in case anyone is interested.

It seems like using window.open() / window.opener is an effective way to get two existing tabs to connect to each other.

The gist of it is that domain B creates a temporary tab which is used to transfer the MessagePort via the SharedWorker.
Once the MessagePort is received, the tab is closed again.
The only thing with this approach is that it requires a user interaction to open the pop up, but that would have been the case with requestStorageAccess() anyway.

Either way, I think this will work for me. Thanks again for all the help!

Reply all
Reply to author
Forward
0 new messages