-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Alternative design: Consider integrating with CORS and HTML and Fetch #3
Comments
If I understand correctly, this doesn't remove the additional round-trip; it converts it into a CORS preflight instead of a traditional GET. Right? And this is all gated on whether the top-level document used the new HTML attribute, so it requires work/coordination from both the top-level and the embed in order to use this properly. IIUC, we'd still need some kind of new response header to allow the server to say "please load this content with storage-access activated", in order to skip the additional round-trip for iframes that don't themselves require auth cookies, but which load subresources that do require auth cookies. (This is what the So IMO, the design you suggest:
So while it sounds nice to reuse CORS infrastructure, I don't think it actually gains us anything, and it seems to make things worse IMO. WDYT? |
Sorry- that should say "I have an idea to remove the additional round-trip mechanism...". I was thinking of complexity of the platform as a constraint here.
Yes, however, now that I look at it again, I am not sure if we need to make these requests non-simple. Simply making these requests protected by CORS should be enough to have an opt-in signal. This would remove the round-trip.
Or iframes with "use-storage-access" just set the
This seems like reasonable usage to me, and probably easier than adding HTTP header-handling for most developers.
This is no worse than
I'll give you this. However, I don't think this is an issue. Forcing better hygiene to use a more performant option is good. |
The problem with this is that this opt-in signal is coming from the embedding site (the one that embeds the subresource), which is (by assumption) different from the embedded site (the one that supplies the subresource). An HTML attribute doesn't let us conclude that the embedded site is opting in. Similarly, we can't use
Maybe your opinion has changed based on what I said above (re: security properties), but if we did require a Considering that we still need a response header to indicate opt-in from the 3p server (IIUC), I think that additionally requiring the HTML attribute would just allow a top-level document to forbid credentialed cross-site subresource requests (by just omitting the attribute everywhere). IMO, the simpler way to achieve that is to apply a storage-access permissions policy of I guess the attribute allows the embedder to be selective about which subresources can use credentials and which can't? But I'm struggling to see the utility of that, considering the user has already given storage-access permission so they do not want to enforce a privacy boundary between this pair of sites. |
The HTML attribute isn't the opt-in signal I was talking about here. The CORS The HTML attribute is a little orthogonal, and is just a way to determine which resources should be unpartitioned. I suppose there is a design principle question here: should the client or the server determine which resources are unpartitioned. I favor the client. That is in line with the Javascript API, leaves room to remove the round trip for unpartitioned resources, and it just makes more sense to me that the document makes decisions about when to try to use unpartitioned cookies. |
Ah, I misunderstood. So if I'm understanding correctly, you're suggesting that the browser would always send 3p cookies if the (And the browser would probably also send 3p cookies even without CORS if the That sounds reasonable to me in terms of privacy/security, and it does avoid the extra round-trip. That's pretty nice. So the remaining piece is the |
Not always, but where an HTML attribute asks for them specifically. And that would force CORS mode.
👍
Thank you!
If the embedee marking the iframe as "use-storage-access" isn't good enough (presumably because only requiring 3rd-party changes is easier in the popular embed use-case?), including a new HTTP Response header for frame content that has the semantics of " |
Hm, on second thought, one intentional property in my original design was that this didn't require any work on the part of the top-level site; the 3p could manage things entirely by itself with the request header and response header. That makes the headers a little different from CORS, since CORS (and the I could certainly see a world where both designs coexist, so that the top-level site can do some work in order to avoid the extra latency from the additional round trip. But I want to avoid introducing an unnecessary requirement that the top-level site must do that work.
The principle I've been using is embeddee vs embedder, rather than server vs client. I.e., the embeddee must be the (only) one that determines which of its resources are fetched using unpartitioned cookies, for security reasons. The embeddee already has the ability to do that on the client (via And conversely, it's important to not require the embedder's participation, because we're already seeing cases where a cross-site resource is embedded in lots of different top level sites (think any SaaS provider). Updating all of those top level sites is not necessarily feasible, nor is it really necessary. |
I get that, and I think that is an important principal. How about an HTML vs Fetch distinction? Because to me, fundamentally what you want to do is alter an environment, and in order to do that it would be best to make changes to the HTML rather than the Fetch. Like throwing a I see |
I assume you're talking about the embeddee's environment, i.e. the iframe case with
Those are also about handling cross-origin requests, but they attack the problem from a slightly different angle. They allow the embedder to ask for credentials to be included in the cross-origin request. I'm trying to give the embeddee a way to ask for credentials to be included in a request to its origin. The embeddee can't supply the IIUC, CORS fundamentally requires opt-in from both parties (the sender/embedder via
I think we ought to be careful about this principle. The embeddee currently doesn't have any ways of asking for their credentials (unless it's capable of executing JS); so I think we ought to count this header as a distinct capability, rather than an additional way of doing something that's already possible. I also think it's ok to have more than one way to do something if one way presents better tradeoffs than the other in some cicumstances. E.g., it's fine to provide the |
Yep! I'm pointing out that the thing whose state we are changing is a Document, so putting the change in HTML is a closer match to the current semantics where the document calls requestStorageAccess. I'm not saying that this would be hard to spec up, just trying to think where we should add this functionality.
Fair! But getting a little creative here: a We should try to support use cases where the web dev doesn't have control of the server where possible, and I think we can. That and not reinventing a CORS-like mechanism are why I'm trying to help here.
Agreed that JS and non-JS ways of doing a thing are distinct capabilities.
👍, agreed |
Ah I see, I misinterpreted! FWIW, CSP and Permissions Policy are two examples of headers that integrate with the HTML spec, so there's precedent for modifying
That's an interesting idea! That feels similar to how Content Security Policy supports delivery via a <meta> tag. I'm not opposed to supporting something like that in the future, to help use cases where the web dev doesn't control the server. I do also want to support use cases where modifying the content isn't an option, though, (since if the content can be modified, then they have options today; they could just call
I've been thinking about this more, and I'm becoming convinced that we do have to reinvent a CORS-like thing:
I think this mechanism and CORS are sort of complementary to each other, and have a lot in common. In particular:
WDYT? |
Catching up with this (thanks for the great discussion!), and at the risk of being biased 😆, I think I'm supportive of Chris' direction and ideas here. Two principles I'd really like to uphold with this proposal:
Since these are both challenges we've heard quite frequently from developers. I also support the idea of reducing reliance on servers (and server libraries) to support the right headers to use SAA, this could be especially helpful in environments where these headers can't be easily modified (CDNs, I think?). However, it feels orthogonal to the problems being attacked by this proposal, and SAA is already usable with only client-side code. Overall I'm skeptical about the overloading of CORS to solve storage access opt-ins as a long term web platform solution. As Chris mentioned, it only gets us halfway there in terms of security benefits. We're using it as the top-level opt-in mechanism for rSAFor, which is criticized as insufficient in privacycg/requestStorageAccessFor#30. Besides that, I've also come to realize that overloading these existing concepts for new exciting purposes often causes additional effort and pain for everyone involved, including the folks who maintain CORS and now have to watch out for side effects they didn't design for. cc @arturjanc There's probably a lot to write about this but I think I'd prefer to not further enshrine it on the web platform until we have more clarity on these questions. We can explore it, though!
Unfortunately yes, I think you're right. |
I am coming around on this being a new header set- the issue specifically being the fallback case. In CORS it is an error and here we would want it to just send without unpartitioned credentials. Okay, it makes sense that we could have these headers co-defined in meta tags. We can punt on the network-only-ness, and just slap on meta http-equiv definitions at the end.
Oof. Looking forward to your writeup on the problem. My gut tells me it may be easiest to forbid retry on non-idempotent request methods, especially due to the change in credentials between the two requests. |
Re: HTML vs Fetch, I also realized that in order to require a change in the HTML (e.g. a |
This comment was marked as spam.
This comment was marked as spam.
Continuing to think about this - I was wrong about needing to design a preflight mechanism, similar to CORS. I wrote up an argument why preflights are unnecessary in adbfd5a. Since CORS preflights are not for protecting the semantics of non-idempotent requests (after all, POST requests aren't preflighted), we don't need to handle non-idempotent requests specially here either; a server can respond with a 4XX and the |
There's been a bunch of discussion on this issue (sorry I missed it, I was OOO and never managed to get to this in my post-Christmas backlog) and I think the proposal has changed in the meantime, so just adding a few random thoughts:
|
This could be addressed with an addition to the fetch's
I missed this argument, but I disagree with this approach. Allowing the use of unpartitioned credentials where you wouldn't otherwise allow partitioned credentials seems unwise. And saving developers the trouble of upgrading their endpoints to CORS is not helpful if we are forcing them to do an equivalent opt-in anyway.
I think the overlap is significant enough that it would be simpler to integrate 😄 |
@bvandersloot-mozilla how would this work with navigational requests and/or requests that the 1P is unable to mark as crossorigin? It feels like the 3P should be able to enforce this mode on its own. |
Reading back- I think I missed the point on this one. If I have it right now, these would be |
I forgot about the no-change-on-the-1p constraint. Combined with my re-read above and the lack of a need for preflights, maybe it would be easier to have independent. I could see either being easier still. I can't shake the feeling that this is about giving the server the power to permit resource sharing based upon the parameters of the request, which is dead on with CORS's purpose in my mental model. |
Yes, in my mental model these are loads via
I see your point, but here we're just talking about granting the capability to send a credentialed request to the resource without exposing the contents of that resource to the requester. If you opt into CORS you grant the requester access to the bytes of the resource (and the resource load can have credentials if the requester sets credentials= With SAA headers you say "I'm allowing this request to have credentials, but I'm not sharing the contents of the resource with you". E.g. imagine a 3P widget that directly renders the user's profile picture as an image on the embedding page (where the 3P knows the user because it's an IdP or something like that); for loads like that we'd want the image to be loaded with credentials, but without CORS to not expose it to the embedder. This obviously gets murky because |
Reading this out, I think this distinction is significant and makes sense to me. |
I have another point, but it strays from integration, so I'm filing #8. |
Thanks all for the discussion. I'll do my best to summarize:
With all that in mind, I think we've reached consensus that CORS ought to be neither necessary nor sufficient for including unpartitioned cookies, and therefore it's best for security (and usability) if the Storage Access Headers are a separate thing, independent from CORS. I'll tentatively close this issue, but feel free to correct me if I've misunderstood anything. |
Continuing from #2.
I have an idea to remove the additional round-trip and to reuse some infrastructure.
This entails two conceptual changes. 1. Move the activation of storage access to the client, rather than the server. 2. Use CORS preflights to maintain server control over whether or not unpartitioned cookies are ever sent.
To accomplish 1, we don't have a
Activate-Storage-Access:
header and use a new HTML attributeuse-storage-access
. This attribute would only be valid on frames or wherecross-origin="use-credentials"
is present and says to use unpartitioned cookies if thestorage-access
permission isGranted
. This would do some stuff in Fetch that makes it use the right cookie jar (cue Johann's cookie layering).To accomplish 2, we need to make the requests with unpartitioned cookies not "simple". That forces a preflight which the server can make security decisions on.
We would still need an informational header to inform the server of whether or not the request was unpartitioned, but may not need the detail about inactivity. Maybe reviving something like Dylan's proposals in w3c/webappsec-fetch-metadata#80 would make sense.
Overall I think this is a cleaner design because it treats unpartitioned credentialed requests as an "unsafe thing" in the construction for "unsafe things" we already have.
The text was updated successfully, but these errors were encountered: