Repository navigation
Allowing top-level communication for cross-origin isolated documents #6364
Description
The current model of cross-origin isolation is incompatible with federated sign-in flows based on popups. Any popup opened by a document with a COOP of same-origin will not be able to communicate with its opener, preventing passing information to the application to which the user wants to sign in (or, commonly, to the identity provider's iframe embedded by that application).
Some background for this decision is in #3740 (comment) and the subsequent discussion.
Based on discussions with developers, it looks like this can become a barrier to adoption of cross-origin isolation and to efforts to enforce better isolation by default. We should give developers a recommended solution for this use case which will not require them to re-architect their applications to remove cross-origin isolation from parts of their application where the user is able to sign in.
The main difficulty is that due to browsers' efforts to disable the sharing of state across storage partitions, APIs which could have potentially been used as a fallback to allow the popup to communicate with its opener (BroadcastChannel, localStorage) are unlikely to be tractable approaches in the long term.
A few possible alternatives:
- Allow
postMessageto be used in situations where COOP caused a browsing context group switch.- This seems awkward in the current design of COOP, but it would be the simplest approach from developers' point of view, because it wouldn't require changes to their client-side code. It also doesn't have cross-site tracking potential to the same extent as other "origin-wide" APIs, such as
localStorageorBroadcastChannel.
- This seems awkward in the current design of COOP, but it would be the simplest approach from developers' point of view, because it wouldn't require changes to their client-side code. It also doesn't have cross-site tracking potential to the same extent as other "origin-wide" APIs, such as
- Build exemptions into the partitioning of BroadcastChannel to allow it to deliver messages between the popup and a same-origin iframe embedded by its opener.
- This would require defining a set of criteria that would be met by legitimate scenarios (e.g. sign-in flows), but which would not allow BroadcastChannel to be used for cross-site tracking. My guess is that this is doable, but may be difficult to justify in a principled way, i.e. any partitioning exemptions would seem somewhat arbitrary.
- Ship WebID.
I do think that something like WebID could be a good long-term solution, but I'm worried that without a short/medium-term alternative we'll make life difficult for developers; an approach like (1) or (2) above could possibly be a reasonable alternative. Given the increasing interest in cross-origin isolation it seems somewhat important for us to figure this out soon.
/cc @annevk @mikewest @camillelamy Any thoughts or other ideas here?
Activity
annevk commentedon Feb 6, 2021
I think I'm missing how
postMessage()doesn't have the same tracking potential.arturjanc commentedon Feb 6, 2021
postMessage()lets you communicate only with a window to which you have a reference (or, possibly in this case, would have had a reference if it wasn't for COOP). The other mechanisms let you share data between all same-origin windows, even if they are in unrelated browsing context groups (possibly restricted by storage partitioning; but at the very least with same-origin windows in other BCGs with the same storage key).So, hypothetically, in a browser without storage partitioning an ad iframe can synchronize state across all 3p contexts with
BroadcastChannelorlocalStorage, but not withpostMessage(). (FWIW this doesn't necessarily make a qualitative difference here; but I could imagine that from a cross-site tracking perspectivepostMessage()may be less concerning.)davidben commentedon Feb 6, 2021
@annevk I agree that
postMessagehas tracking potential for cross-site cases, but I don't think they're quite the same. In the long-term, I think WebID or something similar is the answer. However, in the short term, I think leaving federated auth atpostMessageis preferable to moving it toBroadcastChannel. Tracking withBroadcastChannelrequires the two top-level sites be open concurrently at all.postMessageat least requires the documents reach each other. To track, you'd need to either wait for that to happen (which we can hopefully reduce over time) or you'd need to, e.g., visibly open a popup. That's still not great, hence WebID, but I think it's meaningfully better than theBroadcastChannelversion.Moreover, in the long-term, same-(top-level)-site cross-origin documents also have communication uses. In those cases, neither
postMessagenorBroadcastChannelhave a tracking concerns. For non-broadcast versions of those flows, I think there are good developer ergonomics and performance (wake up fewer documents) reasons to preferpostMessage.annevk commentedon Feb 8, 2021
Apart from the tracking concern there's also an architectural concern as otherwise same-origin documents would now only have
postMessage()as communication channel, supposedly. Not to speak of the impact on browsing context groups, less bfcache opportunities, etc.arturjanc commentedon Feb 8, 2021
I'm probably missing something, but I don't think this would prevent same-origin documents from using the other APIs to communicate, as long as they're within the same storage partition; e.g. top-level same-origin documents could still share data via
localStorage, etc. The goal here is to additionally allow certain kinds of same-origin communication across storage partitions, which isn't disallowed by cross-site tracking protections (you still have direct DOM access to cross-partition same-origin documents), but which is disallowed by cross-origin isolation (because you can no longerpostMessage()to your popup).I'm also curious about the other kinds of impact you mentioned above, it would be helpful to understand these concerns.
What I'm worried about is that without providing COI documents with a recommended API to communicate with their popups, it's likely that developers will use alternative mechanisms to achieve the same goal, e.g. use link decoration in the OAuth popup to redirect back to a document in the application's origin and then use a mechanism like
localStorageto exchange data. This is going to be more clunky and will possibly conflict with other cross-site tracking measures in the future.annevk commentedon Feb 8, 2021
Say A opens A' and A' has COOP and A' and A are same origin. Today that means A doesn't have a
WindowProxyfor A', with this, I guess it would. But somehow onlypostMessage()would be available? Today, A and A' do not share a browsing context group and therefore have independent agent clusters. With this, unclear? Today,WindowProxyreferences are never shared outside a browsing context group. With this, unclear?arturjanc commentedon Feb 8, 2021
Yeah, no disagreement from me here: this would certainly require figuring out a way to pass data around between BCGs intentionally separated by COOP. I guess my question is whether poking a hole for
postMessageand allowing it to work across BCGs would be reasonable, or whether -- for example -- it's more appealing to make exemptions forBroadcastChannelto let it work across storage partitions in some cases (or implement WebID, or ...)I realize that both of the ideas above can be ugly (or turn out to not be feasible), but my guess is that we don't do anything the workarounds built by developers are going to be much worse in the long run.
annevk commentedon Feb 8, 2021
Personally something like WebID seems more reasonable to me long term, but I'm also interested in seeing workarounds that would work in Safari (assuming that Safari ships COOP soonish).
arturjanc commentedon Feb 8, 2021
This is definitely a possible approach, but practically it will mean that -- until WebID ships in most browsers -- authors of OAuth flows will have to switch to one of the workarounds like link decoration + top-level same-origin sharing of state.
annevk commentedon Feb 8, 2021
Well, we discussed OAuth flows while designing COOP and
same-origin-allow-popupsandunsafe-nonewere always meant for those use cases.We also discussed allowing
postMessage()and there were several implementation realities that made this infeasible (though I think for Firefox we're mostly past that now, including on mobile), but I also don't think we really tried to figure out what it would mean. And at this point I'd rather not add more tools to the popup workflow as they cause issues for anti-tracking and bfcache.arturjanc commentedon Feb 8, 2021
I don't want to belabor the point because I agree with you about the background and the difficulty here. But we do have more information today than we did a couple of years ago, which can have a bearing on our decisions. Specifically:
postMessagesupport in COOP. Even if developers can still use workarounds (say, link decoration), it's likely that they aren't the right long-term approach and we shouldn't push developers in their direction.Having
postMessagework for the popup workflow actually seems like the most compelling option from an anti-tracking point of view. Anti-tracking efforts don't restrictpostMessagewith your popups; the fact that you can't use it from a COI context is an artifact of how we specced COOP, rather than being dictated by privacy considerations. It seems worthwhile to think about what workarounds developers will develop here (which I'm worried may be objectively worse from both a privacy and complexity point of view).annevk commentedon Feb 8, 2021
I think the fact that anti-tracking hasn't tackled popups (including
postMessage()) yet is precisely because of OAuth making it hard, but everyone is well aware that they present loopholes that ought to be closed.arturjanc commentedon Feb 8, 2021
I have to say this is news to me; do you have a reference you could point to for this?
Also, I'd find this stance defensible if we had plans to break
postMessageto popups from non-COI contexts, which doesn't seem like it's on the horizon? Otherwise we're just punishing developers who do the right thing and enable COOP+COEP.70 remaining items
arturjanc commentedon Jun 15, 2022
FWIW I've been expecting us to apply this COOP value on the main window of applications that aren't opened in popups, but need to interact with a cross-origin popup (and which want COI so they can't use COOP: SOAP). It seems fairly awkward to use
popupin this context so something likerestrict-propertiesmatches my mental model better.hemeryar commentedon Jun 29, 2022
Just a heads up, since we haven't been able to convince each other and that I've got all the docs/explainers/WPT as restrict-properties and that I'll start putting together patches soon, we'll stick to that. This can always be changed in the future but will require significant effort.
hemeryar commentedon Sep 12, 2022
Just a note for thoughts, something that came up while working on a prototype is what we want to do with names when going to/from a COOP: RP page. Is it acceptable that a window name set by COOP: RP page is then leaked into the next non COOP: RP window? Do we want to force a name cleanup? And if we do is it going to break the regular -> COOP -> regular flow we were worried about in the first place?
annevk commentedon Sep 30, 2022
Thought: make
windows.namereadonly in RP mode? (I wouldn't mind hiding it entirely, e.g., returning the empty string, but that might be a bit much.)(I still struggle to make much sense of
restrict-propertiesby the way. In that yes, properties are restricted, but to me it doesn't really communicate the overall idea at all.)bamtheboozle commentedon Sep 5, 2023
what's the latest status on this?
agektmr commentedon Sep 5, 2023
Secure popup interactions with
restrict-properties- Chrome Developershttps://developer.chrome.com/blog/coop-restrict-properties/
anvipul commentedon Oct 17, 2023
I have made my page cross using isolated using coop: restrict-properties & coep : credentialless. I am using msal & okta for authentication. There are certain use cases where I have to focus and close the popup window, but we can't use these methods directly instead we have to post message to these child windows via window.postMessage. But how can I add listeners to these messages on the popup/child window as I don't have control over it. Has anyone solved this issue?
simon-friedberger commentedon Oct 17, 2023
The explainer says:
Could somebody provide some context on why this was done? Is this an implementation detail and the behavior should be the same as with the additional agent cluster keying?
camillelamy commentedon Oct 17, 2023
@simon-friedberger The behavior is exactly the same as additional agent cluster keying. This is an implementation detail, but we also think that it is easier to reason about than extra keying.
@anvipul We'd like to better understand the impact on not having access to focus and close. My understanding is that you should still be able to login, though an authentication popup might be left behind. Is that correct?
anvipul commentedon Oct 17, 2023
@camillelamy Sometimes user may shift the focus to some other tab (with popup still open) & popup will be hidden behind the browser. Now when user comes back and click again on sign in button, either we can focus the already opened popup or close the previously opened popup and open the new one (in the latter case, we can have popup left behind even though the user has logged in).
anvipul commentedon Oct 19, 2023
@camillelamy, do you have any idea on how we can add event listener on the popup window which is not in our control?
camillelamy commentedon Oct 19, 2023
@anvipul My understanding is that while the flow might still be less ideal (ie you might end up with an extra OAuth popup), the user should still be able to login.
We would really like to avoid exposing
focusandclose, as these functions are often used in popunder scenarios. We'd like to make this kind of attacks harder when targeting pages with COOP restrict-properties.camillelamy commentedon Oct 19, 2023
@anvipul It's not possible to add an event listener on a third party window. The whole point of COOP is to limit the ability of other websites to influence you. However, you can reach out to the owner of the window and ask them about the possibility of adding the event listener. They can then review your request and see if it makes sense for their website.
edseidman commentedon Nov 2, 2023
@camillelamy Reaching out to the owner is not practical. Our scenario is OIDC, and through OIDC or SAML redirects, the origin could switch to any authentication service.
You are correct in stating that the basic successful scenario should work. Our concern is that if a user navigates away during authentication, then we leave abandoned popups in the background. We know that they are there, but there is nothing that we can do about it. Our users will not know about COOP restrictions. They will just think that our application is poorly written.
Do you have any thoughts on an eventual solution to this issue?
DemiMarie commentedon Apr 1, 2025
Generally, I think that the best mechanism for authentication is a full-page redirection flow, with all information carried via the redirection URLs. I will admit that my use-case is somewhat niche, but being able to interrupt the authentication flow (by blocking access to the IdP) and copy-and-paste the URL into a different browser or even VM can be very useful for use-cases such as @QubesOS (disclaimer: I have worked on it professionally).
Embedding the IdP’s iframe into a toplevel page seems very dangerous from a security (spoofing) perspective.