Skip to content

Allowing top-level communication for cross-origin isolated documents  #6364

Open

Description

@arturjanc

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:

  1. Allow postMessage to 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 localStorage or BroadcastChannel.
  2. 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.
  3. 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

  1. annevk commented on Feb 6, 2021

    @annevk
    Member

    I think I'm missing how postMessage() doesn't have the same tracking potential.

  2. added
    topic: cross-origin-embedder-policyIssues and ideas around the new "require CORP for subresource requests and frames and etc" proposal
    on Feb 6, 2021
  3. arturjanc commented on Feb 6, 2021

    @arturjanc
    Author

    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 BroadcastChannel or localStorage, but not with postMessage(). (FWIW this doesn't necessarily make a qualitative difference here; but I could imagine that from a cross-site tracking perspective postMessage() may be less concerning.)

  4. davidben commented on Feb 6, 2021

    @davidben

    @annevk I agree that postMessage has 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 at postMessage is preferable to moving it to BroadcastChannel. Tracking with BroadcastChannel requires the two top-level sites be open concurrently at all. postMessage at 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 the BroadcastChannel version.

    Moreover, in the long-term, same-(top-level)-site cross-origin documents also have communication uses. In those cases, neither postMessage nor BroadcastChannel have 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 prefer postMessage.

  5. annevk commented on Feb 8, 2021

    @annevk
    Member

    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.

  6. arturjanc commented on Feb 8, 2021

    @arturjanc
    Author

    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 longer postMessage() 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 localStorage to exchange data. This is going to be more clunky and will possibly conflict with other cross-site tracking measures in the future.

  7. annevk commented on Feb 8, 2021

    @annevk
    Member

    Say A opens A' and A' has COOP and A' and A are same origin. Today that means A doesn't have a WindowProxy for A', with this, I guess it would. But somehow only postMessage() would be available? Today, A and A' do not share a browsing context group and therefore have independent agent clusters. With this, unclear? Today, WindowProxy references are never shared outside a browsing context group. With this, unclear?

  8. arturjanc commented on Feb 8, 2021

    @arturjanc
    Author

    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 postMessage and allowing it to work across BCGs would be reasonable, or whether -- for example -- it's more appealing to make exemptions for BroadcastChannel to 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.

  9. annevk commented on Feb 8, 2021

    @annevk
    Member

    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).

  10. arturjanc commented on Feb 8, 2021

    @arturjanc
    Author

    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.

  11. annevk commented on Feb 8, 2021

    @annevk
    Member

    Well, we discussed OAuth flows while designing COOP and same-origin-allow-popups and unsafe-none were 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.

  12. arturjanc commented on Feb 8, 2021

    @arturjanc
    Author

    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:

    1. Cross-origin isolation is gaining developer interest beyond what we (or at least I personally) expected, including ideas to enable it as the web default. We can't expect COI to be a niche thing for which developers are willing to jump through significant hoops.
    2. Anti-tracking improvements (storage partitioning) are removing mechanisms that were possible alternatives for this use case at the time we decided we can punt on postMessage support 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 postMessage work for the popup workflow actually seems like the most compelling option from an anti-tracking point of view. Anti-tracking efforts don't restrict postMessage with 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).

  13. annevk commented on Feb 8, 2021

    @annevk
    Member

    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.

  14. arturjanc commented on Feb 8, 2021

    @arturjanc
    Author

    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 postMessage to 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.

  15. 70 remaining items

  16. arturjanc commented on Jun 15, 2022

    @arturjanc
    Author

    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 popup in this context so something like restrict-properties matches my mental model better.

  17. hemeryar commented on Jun 29, 2022

    @hemeryar
    Member

    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.

  18. hemeryar commented on Sep 12, 2022

    @hemeryar
    Member

    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?

  19. annevk commented on Sep 30, 2022

    @annevk
    Member

    Thought: make windows.name readonly 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-properties by the way. In that yes, properties are restricted, but to me it doesn't really communicate the overall idea at all.)

  20. bamtheboozle commented on Sep 5, 2023

    @bamtheboozle

    what's the latest status on this?

  21. agektmr commented on Sep 5, 2023

    @agektmr

    Secure popup interactions with restrict-properties - Chrome Developers
    https://developer.chrome.com/blog/coop-restrict-properties/

  22. anvipul commented on Oct 17, 2023

    @anvipul

    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?

  23. simon-friedberger commented on Oct 17, 2023

    @simon-friedberger

    The explainer says:

    The basic COOP: restrict-properties idea would be to use a single BrowsingContext group, but to increase the keying of Agent Cluster. We would have multiple same-origin documents not be able to synchronously script each other, despite being able to reach each other's Window object.
    Instead of increasing Agent Cluster keying, we introduce a new superset of BrowsingContext group, [...]

    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?

  24. camillelamy commented on Oct 17, 2023

    @camillelamy
    Member

    @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?

  25. anvipul commented on Oct 17, 2023

    @anvipul

    @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).

  26. anvipul commented on Oct 19, 2023

    @anvipul

    @camillelamy, do you have any idea on how we can add event listener on the popup window which is not in our control?

  27. camillelamy commented on Oct 19, 2023

    @camillelamy
    Member

    @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 focus and close, 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.

  28. camillelamy commented on Oct 19, 2023

    @camillelamy
    Member

    @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.

  29. edseidman commented on Nov 2, 2023

    @edseidman

    @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.

    @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?

  30. DemiMarie commented on Apr 1, 2025

    @DemiMarie

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: cross-origin-embedder-policyIssues and ideas around the new "require CORP for subresource requests and frames and etc" proposaltopic: cross-origin-opener-policyIssues and ideas around the new "inverse of rel=noopener" header

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions