privacycg / storage-access

The Storage Access API
https://privacycg.github.io/storage-access/
212 stars 27 forks source link

requestStorageAccess for fetch? #53

Closed colinclerk closed 2 years ago

colinclerk commented 4 years ago

I would be interested in a requestStorageAccess mechanism for fetch() calls made to third parties. We're building an embeddable javascript widget that would like to fetch() from a third party with {credentials: "include"}, but we don't use any iframes.

It looks like we can create an iframe, requestStorageAccess from within, then proxy to the iframe's instance of fetch() via postMessage, but it would be nice if we could shortcut that process with a requestStorageAccess mechanism for our embedder's instance of fetch().

For extra clarity:

Third party cookies blockers prevent widget.com from receiving cookies, regardless of if the cookie has SameSite=None. We'd like to override the blocker with explicit user permission, so SameSite=None cookies are included with the request.

Please let me know if this isn't clear!

johnwilander commented 4 years ago

Hi! Thanks for filing.

document.requestStorage() requires a user interaction in the frame that's making the request. This makes sure that there's no insta-prompting on page load and that there's a signal of user intent when the prompt for storage access is shown (the user interacted with the content that's requesting storage access). Did you have thoughts on how that should work with storage access for fetch?

colinclerk commented 4 years ago

For our use case we're happy to maintain the requirement that requestStorage is tied to a user gesture event.

The event will occur in our embedder's document instead of ours, so semantically the "requestStorage" name wouldn't make sense any more, but I believe the requirements can hold.

annevk commented 4 years ago

So the scenario is that A embeds B, but you want storage access for C? It's probably possible to devise a scheme, but it would have to involve explicit consent from C.

jackfrankland commented 4 years ago

@colinclerk If I understand the result of this issue correctly: https://github.com/privacycg/storage-access/issues/3, once storage access has been granted to a third party, fetch requests from the top-level document to the same third party will also have storage access. This means that you will not need to proxy the third party fetch requests through postMessaging the iframe in order for the fetch to have credentials.

To gain storage access though, I believe the main reason for why the user action needs to be from the third party's iframe, rather than the top-level document, is to verify that the request is being made by the third party. There is currently no trustworthy way of verifying the provenance of script running in a first party context.

To carry on the idea further though, is there a potential solution with response headers from the third party being able to trigger the storage access request, provided other conditions are met?

colinclerk commented 4 years ago

So the scenario is that A embeds B, but you want storage access for C? It's probably possible to devise a scheme, but it would have to involve explicit consent from C.

@annevk There should only be A and B

A is the first party doing the embedding. B is a third party API on a different origin.

"storage access" is a misnomer here, since A never gains access to B's cookies, and B never gains access to A's cookies. Instead, A wants to make fetch requests to B, and wants the browser to send and receive B's cookies when those fetch requests are made.

The traditional approach to this is:

But "storage access" has rightfully called out that coordination between A and B in this manner allows A and B to link identities without the user's consent. I would like the User to be able to offer consent for A to make a request to B that includes cookies.

Does this make more sense?

colinclerk commented 4 years ago

To gain storage access though, I believe the main reason for why the user action needs to be from the third party's iframe, rather than the top-level document, is to verify that the request is being made by the third party. There is currently no trustworthy way of verifying the provenance of script running in a first party context.

To carry on the idea further though, is there a potential solution with response headers from the third party being able to trigger the storage access request, provided other conditions are met?

@jackfrankland please read above and see if that helps clarify the use case at all. I believe the trust mechanism is already there through SameSite and CORS, specifically:

Are these conditions sufficient to build trust, versus leveraging an iframe?

colinclerk commented 4 years ago

@jackfrankland Sorry I didn't to respond to this part:

If I understand the result of this issue correctly: #3, once storage access has been granted to a third party, fetch requests from the top-level document to the same third party will also have storage access. This means that you will not need to proxy the third party fetch requests through postMessaging the iframe in order for the fetch to have credentials

It's unclear to me whether #3 (and the fix) applies to fetch or just multiple frames on the same page. The resolution of "per-page" vs "per-frame" definitely trends that direction, but I'm not seeing any explicit reference to fetch or other resources. I might just need to dive deeper, which I will try to do this weekend.

That is certainly helpful if it's the case, since it would cut out the proxy logic as you suggest. However, I'm not sure if it's a resolution, particularly if CORS and SameSite provide enough confidence that a host is expecting third party requests. If so, requiring the widget provider to use an iframe still feels like an unnecessary step.

jackfrankland commented 4 years ago

@colinclerk yes it's unclear to me too, and it would be good to get confirmation on this, or for it to be firmed up in the spec if not - currently Firefox still sends cookies with cross-origin requests (after storage access is granted), while WebKit does not.

As for the response headers... this is what I was thinking also (if not a new header altogether), along with possibly a new request option in the fetch call to specifically allow for access request if required. The new request option would only be valid upon user activation, and its presence would consume the user activation. No credentials will be sent with this fetch request, and the access request could only be able to occur after the response has been received of course, which I imagine could make this undesirable due to the potential delay. Alternatively, if a separate response has already been received from the third party that has given permission for access to be requested, then perhaps it should be possible to request the access with a new API call.

Please note that it's only my own current understanding of why the user action must be within the third party iframe, and I would be just as interested as you are to see if any extra measures like these for cross-origin fetches would be be deemed acceptable.

colinclerk commented 4 years ago

@jackfrankland Actually, yes, on second thought I want to challenge this idea more fundamentally:

I believe the main reason for why the user action needs to be from the third party's iframe, rather than the top-level document, is to verify that the request is being made by the third party

Is there any reason the request needs to be made by the third party? Why can't the first party want to consume the third party's API directly? At a high level, I see Storage Access prompts as a way of asking the user: "Can firstparty.com share your identity with thirdparty.com?"

I don't believe there's an advantage to be gained from firstparty.com asking for permission to share identity with arbitrary third parties. I'm not sure I understand how forcing thirdparty.com to acknowledge that it wants its own cookies (by way of an early iframe or an early HTTP header) adds additional protection.

Perhaps there's a way this concept offers better CSRF protection than what's afforded by CORS and SameSite, but I'd really want to understand the attack it's protecting against that CORS and SameSite don't, especially in a world where SameSite defaults to Lax.

annevk commented 4 years ago

The third party needs to be involved as it receives (part of) the blame and holds the authority over the data involved.

annevk commented 2 years ago

Let's dupe this into #107.