Skip to content
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

[css-view-transitions-2] Support same-site cross-origin view transitions #10364

Open
khushalsagar opened this issue May 23, 2024 · 13 comments
Open
Labels
css-view-transitions-2 View Transitions; New feature requests

Comments

@khushalsagar
Copy link
Member

khushalsagar commented May 23, 2024

The cross-document spec currently limits transitions to Document in the same-origin. This misses a common use-case of transitions on same-site cross-origin navigations: a.example.com -> b.example.com.

Since there is a security boundary between each origin, and transitions require sending the captured element data from the old Document to the new Document, this can't be done by default. But it should be feasible if both Documents opt-in to transitions from each other.

The above can likely be added to the @view-transition rule using 2 descriptors: from/to. Where the descriptor provides the URLs for Documents which it permits transitions from or to. The default value (same-origin?) would limit to only same-origin URLs. Something like on a.example.com:

/* Applies to all same-origin navigations */
@view-transition {
  navigation: auto;
}

@view-transition {
  navigation: auto;
  from: url-pattern("https://b.example.com/*");
}

The idea of from/to was discussed on #8925 and this is a good use-case which needs it.

We can also add a keyword like same-site to opt-in to transitions from/to any same-site URL.

@vmpstr @noamr @bramus @jakearchibald @nt1m

@khushalsagar khushalsagar added the css-view-transitions-2 View Transitions; New feature requests label May 23, 2024
@khushalsagar
Copy link
Member Author

If we're ok with script to start with (since url-pattern will have to be its own addition to css), we can also just start with the same-site keyword. So from/to can take 2 keywords: same-site and same-origin with the default being same-origin. Authors can do per URL filtering using the pageswap event which provides the destination URL.

@noamr
Copy link
Collaborator

noamr commented May 24, 2024

Note also that NavigationActivation and pageswap have relevant same-origin restrictions that would have to be relaxed for this to work.

@khushalsagar
Copy link
Member Author

Note also that NavigationActivation and pageswap have relevant same-origin restrictions that would have to be relaxed for this to work.

Good point! Can you think of any issues with relaxing the restriction, if the site has a vt opt-in?

@SebastianZ
Copy link
Contributor

SebastianZ commented May 24, 2024

How about adding a new Content Security Policy (CSP) directive for this instead?
That would make this feature very flexible and even allow to opt into different-site cross-origin view transitions, plus, it's a little faster than defining it in CSS because it's defined within a header and it aligns well with other CSS-related features like font-src.

Sebastian

@khushalsagar
Copy link
Member Author

How about adding a new Content Security Policy (CSP) directive for this instead?

Love it! Especially with the example of font-src you mentioned. We'd likely still want from/to eventually so authors can do transition customization declaratively. But since opt-ing into same-site cross-origin transitions is a security policy, CSP seems like a better place for it.

even allow to opt into different-site cross-origin view transitions

Different-site cross-origin is fundamentally harder to do for multiple other reasons:

  • View Transitions work by sharing metadata and a handle to snapshots of the old Document with the new Document. From a security standpoint, that's highly sensitive information to share cross-site (even if there is an opt-in).
  • The fact that the previous site initiated a View Transition, and the details in the metadata passed over to the new site, can be used as a vector for passing information and user fingerprinting.
  • View Transitions work by allowing the new Document to customize the animation using static state from the old Document. For cross-site, this would allow the new site to decide what the animation looks like. And it's not clear whether either site should unilaterally control what the animation looks like.

This is not to say cross-site is completely infeasible, but it needs a deeper dive into what control we actually want to give to authors vs letting majority of the experience to be defined by the UA.

@noamr
Copy link
Collaborator

noamr commented May 25, 2024

Note also that NavigationActivation and pageswap have relevant same-origin restrictions that would have to be relaxed for this to work.

Good point! Can you think of any issues with relaxing the restriction, if the site has a vt opt-in?

The vt opt in itself is not enough because you can't read it in the old page before the new page is parsed. CSP is perhaps more suitable because it can be delivered in HTTP headers.

But the main restriction that's going to have to be relaxed is on navigation API session history, as for effective cross-doc navs you need to know where you're going to post-redirects and also where you came from (which might not be the referrer if you're traversing). Currently all of this is same-origin. There are not many things that are same-site protected and it's challenging to get right.

I can't tell if a CSP opt-in is enough for this, it's a good conversation to have with security folks. My point is if we were to do this I would start from history and derive view transitions from that rather than jump straight to CSS.

@noamr
Copy link
Collaborator

noamr commented May 25, 2024

How about adding a new Content Security Policy (CSP) directive for this instead? That would make this feature very flexible and even allow to opt into different-site cross-origin view transitions, plus, it's a little faster than defining it in CSS because it's defined within a header and it aligns well with other CSS-related features like font-src.

Note that CSP is designed as an opt-out only, meaning any added policy can only be further restricting what precedes it or the default. It's not a good framework for something that's supposed to be restricted by default and relaxed using an opt-in.

@khushalsagar
Copy link
Member Author

My point is if we were to do this I would start from history and derive view transitions from that

That's fair. We might need 2 policies, one to allow same-site URLs to be visible in the navigation API session history and another for view-transition. And the view-transition can't apply without a navigation API opt-in.

Note that CSP is designed as an opt-out only, meaning any added policy can only be further restricting what precedes it or the default. It's not a good framework for something that's supposed to be restricted by default and relaxed using an opt-in.

Can you expand on "designed as an opt-out only"? Since on the surface it looks like a key -> list of URLs, it's not obvious why that list can't be used as an allow list on top of any same-origin URL.

@noamr
Copy link
Collaborator

noamr commented May 27, 2024

My point is if we were to do this I would start from history and derive view transitions from that

That's fair. We might need 2 policies, one to allow same-site URLs to be visible in the navigation API session history and another for view-transition. And the view-transition can't apply without a navigation API opt-in.

Note that CSP is designed as an opt-out only, meaning any added policy can only be further restricting what precedes it or the default. It's not a good framework for something that's supposed to be restricted by default and relaxed using an opt-in.

Can you expand on "designed as an opt-out only"? Since on the surface it looks like a key -> list of URLs, it's not obvious why that list can't be used as an allow list on top of any same-origin URL.

CSP is a list of policies, each policy with multiple directives. Every policy can only tighten what's before it, not relax it. It's built in a way that a policy injected (eg in a CDN header) can't relax security beyond the current state.

@bramus
Copy link
Contributor

bramus commented May 27, 2024

My gut reaction was to have an opt-in through CSS, as not all authors have control over setting the headers.

@view-transition {
  navigation: auto;
  origins: a.example.com, b.example.com; /* Or maybe even `*.example.com`? */
}

I would prefer to explicitly list the origins here, so that in the future – if it ever would become a thing – cross-origin VTs can use the same descriptor to include other sites.

@view-transition {
  navigation: auto;
  origins: *.example.com, *.example.org;
}

(Note: I’m not suggesting to add cross-site support here and now; am merely thinking ahead to make sure the syntax can support that, if needed)

An alternative would be to allow a combination of the values same-origin, cross-origin, same-site, cross-site for the suggested descriptor but in that case:

  • One could end up with a faulty combination of same-origin cross-site.
  • I’m not sure how one would list the allowed origins/sites.
    • Maybe something like Related Party Sets (fka “First Party Sets”) could be used in that case?

@natechapin
Copy link

Note also that NavigationActivation and pageswap have relevant same-origin restrictions that would have to be relaxed for this to work.

Good point! Can you think of any issues with relaxing the restriction, if the site has a vt opt-in?

The vt opt in itself is not enough because you can't read it in the old page before the new page is parsed. CSP is perhaps more suitable because it can be delivered in HTTP headers.

But the main restriction that's going to have to be relaxed is on navigation API session history, as for effective cross-doc navs you need to know where you're going to post-redirects and also where you came from (which might not be the referrer if you're traversing). Currently all of this is same-origin. There are not many things that are same-site protected and it's challenging to get right.

I can't tell if a CSP opt-in is enough for this, it's a good conversation to have with security folks. My point is if we were to do this I would start from history and derive view transitions from that rather than jump straight to CSS.

Do I understand correctly that this would require navigation.activation.from to be populated in the cross-origin-but-same-site case?

I think that's probably doable if both origins consent to it, but it would be important to note that some of the information on navigation.activation.from would be incomplete or unusuable. Most notably, a from.key would be rejected if given to navigation.traverseTo, and from.index would always be -1.

We would also need to think carefully about from.url behaves. Would it be ok for it to be origin-only? Would it break view transitions if it was censored due to referrer policy?

@khushalsagar
Copy link
Member Author

Do I understand correctly that this would require navigation.activation.from to be populated in the cross-origin-but-same-site case?

Yes, the Document would need this information to customize the transition.

I think that's probably doable if both origins consent to it, but it would be important to note that some of the information on navigation.activation.from would be incomplete or unusuable. Most notably, a from.key would be rejected if given to navigation.traverseTo, and from.index would always be -1.

Can you expand on this a bit more? My thinking was that an opt-in from 2 same-site cross-origin URLs means we can expose all the information that is provided by the navigation API to same-origin URLs. Is there a reason we shouldn't do that? And specifically about your comment for traverseTo, do you think this opt-in should only provide readonly state but not allow authors to do actions provided by the navigation API..?

@noamr
Copy link
Collaborator

noamr commented Jul 10, 2024

A path forward to allowing this could be to expand on what we can do declaratively, and then restrict the JS access to the transition if it's cross-origin.

In essence, do the following:

  • Introduce something like [css-view-transitions-2] Syntax for navigation-matching #8925 where the view-transition can be enabled/customized (using types) based on which origin it's going to
  • Both sides have to explicitly opt-in to a view-transition for that particular origin
  • Perhaps even limit this to first-party-sets, and gate by referrer policy. This addresses other issues such as user confusion about "which origin am I on" and issues like passing side-channel information inside a view-transition list of captured elements.
  • View transitions would have to be expressive enough without old-document script access to the post-redirect origin, and without a web-visible extra rendering cycle that captures the view transition.
  • I'm not sure if we can/want to support cross-origin back/forward navigations. Perhaps the default for cross-origin navigations should be ordinary navigations and one has to explicitly add traverse as a type to @view-transition
  • We can consider allowing a special type of consent for root-only transitions as those don't expose information about the old page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-view-transitions-2 View Transitions; New feature requests
Projects
None yet
Development

No branches or pull requests

5 participants