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

Open Window Algorithm and tracking through 1ps #351

Open
pes10k opened this issue Oct 28, 2019 · 33 comments
Open

Open Window Algorithm and tracking through 1ps #351

pes10k opened this issue Oct 28, 2019 · 33 comments
Labels
privacy-tracker Group bringing to attention of Privacy, or tracked by the Privacy Group but not needing response.

Comments

@pes10k
Copy link

pes10k commented Oct 28, 2019

I am attempting to understand the "Open Window Algorithm" section of the spec. My understanding is that it would allow (say) example.com to open and interact w/ 3p domains (those of the payment handlers) but in a 1p / top-level-context.

If Im reading this correctly, this would enable types of tracking that other parts of the web platform are trying to address (specifically, double-keying, or partitioning, storage by 1p-3p to prevent the 3p from tracking the user across the web). If I read the spec correctly, the standard would allow the payment processor to track the user across pages that use the processor, since the processor would always have access to the same global storage, instead of different storage for each 1p it appears under.

Updating the spec so that open window doesn't create a top-level-context, but a 3p context, would solve this problem, and would be inline with the privacy protections being pursued by partitioning storage, Storage Access API, etc.

@ianbjacobs
Copy link
Contributor

Hi @snyderp,

Thanks for raising an issue.

One quick note: the merchant does not open the payment handler. The user chooses
(and launches) a payment handler to respond to a payment request. Once the payment handler is running, the merchant and payment handler can interact through a small set of events defined in Payment Request API and Payment Handler API.

I have a couple of questions:

  • Today users are often redirected to payment services, which also seem to be top-level contexts. Our thinking is that this is analogous to that, except a better user experience through a modal window. Does your comment about 3p context also apply to those sorts of redirects?

  • Payment services know to whom I am making a payment. When you refer to tracking users, do you have in mind tracking beyond that knowledge of who is the beneficiary?

Thanks!

Ian

@pes10k
Copy link
Author

pes10k commented Oct 28, 2019

Howdy @ianbjacobs!

Today users are often redirected to payment services, which also seem to be top-level contexts. Our thinking is that this is analogous to that, except a better user experience through a modal window. Does your comment about 3p context also apply to those sorts of redirects?

It depends on the details of those redirection flows, how deeply nested they are, etc. Safari, for example, prevents some sites that are part of redirection flows from keeping state (ITP2.x) (those that it thinks are tracking). Brave and Safari both strip query params from some URLs to prevent sites from pushing information between 1p contexts. There are browser extensions that do similar things, and other browsers may, or may plan to, do other things that I'm not familiar with.

So, its all depends, but the overall point is that if payment.com is opened up from example1.com, and also opened from example2.com, payment shouldn't be able to link those two events from that activity alone.

Payment services know to whom I am making a payment. When you refer to tracking users, do you have in mind tracking beyond that knowledge of who is the beneficiary?

Not all visits to the checkout / payment page result in entering information (some users decide not to purchase). And some visitors may want to maintain different identities with the same payment provider, so (for a variety of reasons) may choose to present one identity payment.com when buying boring things, and might present another identity to payment.com when buying sensitive things. (e.g., paying for insurance and paying for a cancer screening).

@ianbjacobs
Copy link
Contributor

hi @snyderp,

It depends on the details of those redirection flows, how deeply nested they are, etc. Safari, for
example, prevents some sites that are part of redirection flows from keeping state (ITP2.x) (those > that it thinks are tracking).

So an interesting question is: what information can be sent by the merchant to the payment handler once the user selects the payment handler to pay? The Payment Handler API defines some data for the browser to hand to the payment handler. This is data deemed necessary for the transaction to take place:
https://w3c.github.io/payment-handler/#the-paymentrequestevent

The browser passes the origin of the merchant site (and the origin of the party that called Payment Request API, e.g., if from an iframe).

In addition, a payment method definition can include its own "request data" (e.g., information to identify the merchant to the payment handler).

Not all visits to the checkout / payment page result in entering information (some users decide not to purchase).

That would be the same as if the user were to cancel the payment handler before completing payment.

And some visitors may want to maintain different identities with the same payment provider, so
(for a variety of reasons) may choose to present one identity payment.com when buying boring
things, and might present another identity to payment.com when buying sensitive things. (e.g.,
paying for insurance and paying for a cancer screening).

I believe that the payment handler approach would support that use case. A (Web-based) payment handler is a Web site, so the user should be able to interact with it with different identities.

@pes10k
Copy link
Author

pes10k commented Oct 30, 2019

So an interesting question is: what information can be sent by the merchant to the payment handler once the user selects the payment handler to pay?

My concern isn't related to the information that can be exchanged, its related to which storage the web payment handler context receives. If the frame is a 1p context, that will allow for tracking to occur across 1p pages. If its a 3p context (and so all the restrictions placed on nested contexts would apply) then most methods of tracking are prevented.

That would be the same as if the user were to cancel the payment handler before completing payment.

I believe that the payment handler approach would support that use case. A (Web-based) payment handler is a Web site, so the user should be able to interact with it with different identities.

Again, my concern is not whether the API would allow people to long in with multiple identities, its that the spec, as written, would allow the payment handler to link those multiple presented identities together (since they're all happening in the same storage context). Having the context be 1p / top level makes that possible; having it be 3p / nested-context prevents most methods of that, since the storage the payment handler context gets when opened from store1.com would be distinct from the storage the payment handler context gets when opened from store2.com

@rsolomakhin
Copy link
Collaborator

the storage the payment handler context gets when opened from store1.com would be distinct from the storage the payment handler context gets when opened from store2.com

Would this mean that I have to login into Google Pay separately on each merchant website?

@pes10k
Copy link
Author

pes10k commented Nov 4, 2019

By default yes (the same storage that allows not-logging-in also enables tracking)

https://developer.mozilla.org/en-US/docs/Web/API/Document/requestStorageAccess is one method that would both reduce tracking and remove the need to login repeatedly though.

So, well behaved sites would not require multiple logins

@danyao
Copy link
Contributor

danyao commented Nov 7, 2019

Thanks @snyderp for raising these thoughts. I understand the importance of locking down 3P iframes. Where I respectfully disagree is that the payment handler is not a 3P context the same way iframe is. It's more like a nicely positioned popup because:

  1. It can only be triggered with a user gesture, unlike iframe or redirect which happen automatically at the embedder context's discretion.
  2. It contains a URL bar that shows the origin the user is interacting with, unlike iframe where the origin is hidden.
  3. The embedder context cannot play with its visibility or overlay other content on top of it, unlike iframe which can be made transparent or hidden behind other layers.

I'd argue that the payment handler window is not fundamentally different from a new tab that's triggered by the user clicking on an <a href="..." target="_blank">, so it shouldn't be subject to the storage partition ideas for 3P iframes.

Again, my concern is not whether the API would allow people to long in with multiple identities, its that the spec, as written, would allow the payment handler to link those multiple presented identities together (since they're all happening in the same storage context)

If I click on a link to ewallet.com from store1.com, log in with account1, and then click on a link to ewallet.com from store2.com and log in with account2, ewallet.com can also link my two identities. Being able to follow links is a fundamental property of the web. The only question is, how different is the payment handler pattern different from following links? I'd argue it's pretty similar, because user sees a "Pay with eWallet" button, clicks on it. It shouldn't be a surprise to them that we load a page from ewallet.com.

Other features of the Payment Handler API arguably needs more thought. For example, the Just-in-Time Install feature causes the browser to download a manifest from a payment app origin that's specified by the merchant, without user guesture. However, Chrome's implementation doesn't send any cookies on this request. I believe we also don't allow setting any cookie on the response, but need to check. If it does, it's a bug and we'll fix it.

A bad actor can trick the user into clicking on something that opens a payment handler window to accomplish tracking. But the effect is very intrusive, so it doesn't seem to me that it will be a very successful exploit. Also browsers implementing the payment handler window can monitor how origins use Payment Request API. If there's good reason to believe this API is not used for legitimate e-commerce use cases and can prevent these attacks similar to how Safe Browsing works today.

@pes10k
Copy link
Author

pes10k commented Nov 7, 2019

I'd argue that the payment handler window is not fundamentally different from a new tab that's triggered by the user clicking on an <a href="..." target="_blank">, so it shouldn't be subject to the storage partition ideas for 3P iframes.

The difference is that different tabs / 1ps cannot communicate with each other. Thats exactly how cross site tracking is accomplished, and what 3p containment protects against. You can test this, for example, by clicking a cross-domain <a target=_blank> link in safari, and then noticing that window.opener is null. In general, you will find few places where 1p contexts can communicate with each other, and the few that exist are being actively addressed / worked on for removal.

If I click on a link to ewallet.com from store1.com, log in with account1, and then click on a link to ewallet.com from store2.com and log in with account2, ewallet.com can also link my two identities.

I don't understand this claim That is not true with out some common hook to tie account1 to account 2. If you have segmented (3p) storage, the ewallet.com lacks that common hook.

But further, consider other types of tracking you're enabling:

  1. I click on the link to ewallet.com and then decide not by anything
  2. I click on ewallet.com, it opens for a second, stores the tracking cookie, transmits the cookie back to the site I came from (store1.com) and now store1.com, store2.com and ewallet.com can all collude to share information. This is not possible if ewallet.com gets segmented storage.
  3. More broadly, if all thats needed is a user gesture to get a common / global 1p storage, my analytics script can use that to track users across all sites (e.g. anytime the user is trying to leave the site, spin up this modal window, cookie sync, and then let them leave). That would undo 100% of the benefit of partitioned storage.

Being able to follow links is a fundamental property of the web.

This is not at all like following links on the web. Tracking user across link clicks is currently accomplished by using the referrer header and / or query parameters. Browsers (Safari, Brave, Firefox) are all working on ways of preventing exactly this. The proposal as is would re-introduce the privacy harm currently being worked on / solved by these platforms. The issue here has nothing to do with following links, and all about what 1p contexts can learn about the behavior of the user in other 1p contexts.

@danyao
Copy link
Contributor

danyao commented Nov 8, 2019

In general I agree that there needs to be more control over arbitrary cross-origin communication. I'm still learning the different mechanisms. Thanks for being patient with me.

The difference is that different tabs / 1ps cannot communicate with each other. Thats exactly how cross site tracking is accomplished, and what 3p containment protects against. You can test this, for example, by clicking a cross-domain <a target=_blank> link in safari, and then noticing that window.opener is null.

window.opener is also null inside a payment handler window today. I think this makes sense to keep, so we can modify the spec and add WPTs to make this a requirement.

If I click on a link to ewallet.com from store1.com, log in with account1, and then click on a link to ewallet.com from store2.com and log in with account2, ewallet.com can also link my two identities.

I don't understand this claim That is not true with out some common hook to tie account1 to account 2. If you have segmented (3p) storage, the ewallet.com lacks that common hook.

This is what I was thinking:

  • I click on a link to ewallet.com from store1.com
  • I login on ewallet.com with account1 -> ewallet.com plants a cookie that says "account1"
  • Some time later, I click on a link to ewallet.com from store2.com
  • ewallet.com reads their cookie and discovers that I'm "account1". They offer a choice for me to switch account.
  • I login with account2. Now ewallet.com knows that "account1" and "account2" are associated with the same browser profile.

But further, consider other types of tracking you're enabling:

  1. I click on the link to ewallet.com and then decide not by anything
  2. I click on ewallet.com, it opens for a second, stores the tracking cookie, transmits the cookie back to the site I came from (store1.com) and now store1.com, store2.com and ewallet.com can all collude to share information. This is not possible if ewallet.com gets segmented storage.

I feel I'm missing some key insight to understand why segmented storage helps here. Would you help me understand? Assuming the cookie ewallet.com sends back to store1.com contains some ID for the user that ewallet.com understands, and it's this cross-origin transmission that allows tracking, why can't ewallet.com and store1.com accomplish the same via a server-side backend communication? This should be possible since we already assume they are colluding.

  1. More broadly, if all thats needed is a user gesture to get a common / global 1p storage, my analytics script can use that to track users across all sites (e.g. anytime the user is trying to leave the site, spin up this modal window, cookie sync, and then let them leave). That would undo 100% of the benefit of partitioned storage.

I agree theoretically you could do this. However, I suspect the fact that the tracking is not completely seamless (because a modal will open) would make this not a very useful mechanism to deploy trackers. We can make it even harder by having the browser require another user gesture inside the payment handler modal to dismiss the modal. This will not add any friction to legitimate use cases but would make an attempted attack very visible to the user. If this experience persists, they probably wouldn't come back to the site again. I feel this may be a sufficient disincentive for this abuse of payment handler.

Being able to follow links is a fundamental property of the web.

This is not at all like following links on the web. Tracking user across link clicks is currently accomplished by using the referrer header and / or query parameters. Browsers (Safari, Brave, Firefox) are all working on ways of preventing exactly this.

Removing referrer header seems a reasonable proposal. How would removing query parameters work? Would I no longer be able to link to a page with query parameters?

@pes10k
Copy link
Author

pes10k commented Nov 9, 2019

I feel I'm missing some key insight to understand why segmented storage helps here. Would you help me understand?

Segmented storage prevents this kind of tracking because when ewallet.com is a 3p of store1.com, it gets a separate cookie jar (and other storage) than when ewallet.com is a 3p of store2.com. The distinct cookie jars (sometimes called double-key-ing storage, since (store1.com, ewallet.com) gets distinct storage from (store1.com, ewallet.com)) prevents ewallet from connecting the two sessions.y b

I agree theoretically you could do this. However, I suspect the fact that the tracking is not completely seamless (because a modal will open) would make this not a very useful mechanism to deploy trackers

Unfortunately, the web platform is full of privacy harms that start exactly this way "sure its possible, but no way anyone would ever use it". Partial list includes etags, HSTS cookies, communicating across tabs using nested iframes, 1000 different sources of fingerprinting entropy, etc etc etc etc. If there is a way to track, you can be sure someone, somewhere will use it

Removing referrer header seems a reasonable proposal. How would removing query parameters work? Would I no longer be able to link to a page with query parameters?

This differs by browsers (Safari strips all query params when the user is coming from a labeled tracking domain, Brave ships a set of query params used by known trackers, etc), but is getting increased focus. There is no perfect solution right now, but things are in a "lets not make the problem worse while we try to solve it" scenario.

@danyao danyao closed this as completed Nov 16, 2019
@danyao danyao reopened this Nov 16, 2019
@danyao
Copy link
Contributor

danyao commented Nov 18, 2019

I think the problem boils down to this: both legitimate payment handlers and trackers would want to access 1P storage with minimal user friction. Browsers need to allow legitimate use cases while blocking trackers.

Segmented storage blocks 1P storage by default and relies on browser heuristics to remove as much user friction as possible for well-behaved websites that use Storage Access API. For example. Safari suggested automatically granting requestStorageAccess() calls that are triggered by user gesture, and only prompts if the browser suspects some funny business is going on [1]. Microsoft seems to be planning something similar from talking to them at BlinkOn last week. I understand that Brave had made a different decision to always prompt by default [2].

What about this alternative approach: instead of blocking storage access, browser can use an algorithm similar to that for granting storage access [3] to block PaymentRequest.show()?

I believe this is better than the segmented storage approach in two ways:
The risk of a tracker masquerading as a payment handler is more than access storage: the payment handler window itself, because it looks like native UI, is a powerful feature that needs to be restricted to only legitimate use cases to avoid losing user trust. Blocking access before the open window algorithm triggers solves this problem.
Once a payment handler is “vetted” in a browser, developers can reuse their existing flows without modification.

Browser can work with the user to “vet” payment apps that they trust. For example, browser can show a permission prompt when installing a payment handler with something like "Do you wish to install https://ewallet.com as a payment method that you can use across the web?" An affirmitive answer would allow this payment app to be loaded in the open window algorithm. Or, browser can prompt the user when PaymentRequest.show() is called, e.g. “Do you wish to complete this transaction with ewallet.com?”, and offer an option to never prompt again. Chrome doesn’t do any of these today, but if folks feel this is sufficient we can doing some UX exploration.

While this model still allows some communicaton between 1P contexts (i.e. the merchant context and the payment app context), the user vetting process above limits the capability to only payment apps known and trusted by the user. Also because the communication is via Payment Request API instead of the generic postMessage, this leaves room for browser to detect and restrict abuse.

Lastly, we’ll make sure all the obvious loopholes are closed in the Payment Handler API, i.e.: window.opener and document.referrer are null.

[1] whatwg/html#3338 (comment)
[2] whatwg/html#3338 (comment)
[3] https://developer.mozilla.org/en-US/docs/Web/API/Document/requestStorageAccess

@pes10k
Copy link
Author

pes10k commented Nov 18, 2019

Safari suggested automatically granting requestStorageAccess() calls that are triggered by user gesture, and only prompts if the browser suspects some funny business is going on

I don't see anything about "automatically granting". The user gesture part is a requirement, but isn't access itself.

Browser can work with the user to “vet” payment apps that they trust, etc…

The browser doesn't need a long list of new, hard to reason about, hard to compose guesses for when privacy isn't needed. I appreciate, from your perspective "what's one more little exception", but that is the way that privacy on the platform will continue to crumble; a long list of growing exceptions.

More specifically, can you say how your proposal for PaymentRequest.show differs from the one requestStorageAccess? Are you proposing the exact same algorithm, just with different words in the user prompt? If thats the case, I would be fine with this; but I don't understand how it differs from the original request, to make the payment handler context a standard 3p content. I don't mean any argument, im just trying to understand the current suggestion.

Also because the communication is via Payment Request API instead of the generic postMessage, this leaves room for browser to detect and restrict abuse

Can you say more about this? Any communication channel can quickly be converted to transmit arbitrary data

@danyao
Copy link
Contributor

danyao commented Nov 19, 2019

Safari suggested automatically granting requestStorageAccess() calls that are triggered by user gesture, and only prompts if the browser suspects some funny business is going on

I don't see anything about "automatically granting". The user gesture part is a requirement, but isn't access itself.

I'm referring to this part of @othermaciej's comment:

"Although prompting is allowed by our proposal, we expect in most cases we will just grant the permission without prompting, as the user action is sufficient. We will prompt only if we suspect some funny business is going on, and even then we may just choose to always deny."

The browser doesn't need a long list of new, hard to reason about, hard to compose guesses for when privacy isn't needed. I appreciate, from your perspective "what's one more little exception", but that is the way that privacy on the platform will continue to crumble; a long list of growing exceptions.

I understand we don't want yet another straw. I care very much about Payment Handler API not being abused for non-payment use cases. Suppose I can distinguish perfectly a payment use case from others, and only allow a legitimate payment app to use the open window algorithm to access 1P storage, would you still consider this a privacy hole?

What I'm trying to understand is whether the concern is the abuse potential of the API or whether you don't see any legitimate use case at all.

More specifically, can you say how your proposal for PaymentRequest.show differs from the one requestStorageAccess?

Are you proposing the exact same algorithm, just with different words in the user prompt? If thats the case, I would be fine with this; but I don't understand how it differs from the original request, to make the payment handler context a standard 3p content. I don't mean any argument, im just trying to understand the current suggestion.

The main difference is that the proposal can reject PaymentRequest.show before the payment handler context is even constructed. This is doable because show is called from the merchant context. It is not possible with requestStorageAccess because it is called from the embedded context.

From the user's perspective, the difference can be much smaller. In both cases, the user clicks on something and then sees a permission prompt with some message. I'd prefer reusing the same prompt UI if possible because it seems less confusing to users. I'll need to talk to our UX folks.

Also because the communication is via Payment Request API instead of the generic postMessage, this leaves room for browser to detect and restrict abuse

Can you say more about this? Any communication channel can quickly be converted to transmit arbitrary data

Admittedly this idea needs more exploration. My initial thinking is that the Payment Request API is designed to serve a specific use case, so we may be able to leverage domain specific knowledge to prevent abuse. For example, we can use signals such as the total amount, completion rate to check if a payment handler is likely real or not. Browsers can also develop heuristics for detecting e-commerce websites and known payment apps and block suspicious "payment handlers" similar to Safe Browsing.

@pes10k
Copy link
Author

pes10k commented Nov 19, 2019

I'm referring to this part of @othermaciej's comment:

Ah, thank you for pointing that out. I did not catch that, my error. However, I don't think something like that can be embedded in a spec, w/o defining what "funny business" is, and the privacy of a spec shouldn't turn on unstated heuristics of what "funny business" is, so I think it best to focus on the algorithm described in the spec.

What I'm trying to understand is whether the concern is the abuse potential of the API or whether you don't see any legitimate use case at all.

The concern is (i) the abuse potential, and (ii) the worry about adding privacy debt to the platform through something that gets misused in a way we can't foresee.

So, I'm not saying that there's no legit use cases, or that there is no way to get the feature safe, just that there should be a strong precautionary principal in place (and that "lets make an exception for my feature" is a common thing I hear, that is definitely not inline with caution, not saying that thats what you said :).

The main difference is that the proposal can reject PaymentRequest.show before…

The concern here is that there doesn't seem to be a way that I can use the payment handler w/o giving it 1p storage. E.g. I have to give the context all or nothing, where 2y'd storage is in place to prevent putting users in this situation. Is there a way you can structure / order things where I can use the payment handler, w/o giving 1p storage?

The requestStorageAccess approach would seem to solve both use cases in my mind. By default I could save my self having to type in address info when reusing the same payment handler on the same site, and if wanted, the payment handler could use requestStorageAccess() to get the same privilege across all sites. Im not trying to be dense, but what use case am I missing?

Admittedly this idea needs more exploration. My initial thinking is that the Payment Request API is designed to serve a specific use case…

I would be interested in hearing more, but in general, I think you should start with the assumption that that any communication channel can ultimately be leveraged for arbitrary communication. Also note that any heuristic that depends on "did X match Y" or similar has likely already let some information pass and the cats already out the door…

@danyao
Copy link
Contributor

danyao commented Dec 10, 2019

I'm referring to this part of @othermaciej's comment:

Ah, thank you for pointing that out. I did not catch that, my error. However, I don't think something like that can be embedded in a spec, w/o defining what "funny business" is, and the privacy of a spec shouldn't turn on unstated heuristics of what "funny business" is, so I think it best to focus on the algorithm described in the spec.

The current algorithm as described in [1] leaves prompting to browser discretion. I think this is refers to browser's heuristic on detecting "funny business".

[1] https://developer.mozilla.org/en-US/docs/Web/API/Document/requestStorageAccess

What I'm trying to understand is whether the concern is the abuse potential of the API or whether you don't see any legitimate use case at all.

The concern is (i) the abuse potential, and (ii) the worry about adding privacy debt to the platform through something that gets misused in a way we can't foresee.

So, I'm not saying that there's no legit use cases, or that there is no way to get the feature safe, just that there should be a strong precautionary principal in place (and that "lets make an exception for my feature" is a common thing I hear, that is definitely not inline with caution, not saying that thats what you said :).

I agree with both of your goals. I think the best next step is to elaborate on the privacy / security model of Payment Handler API, and enumerate, as exhaustively as possible, privacy attack vectors. Then we can decide if 3P storage are an effective mitigation to these threats.

Separately, I'll also start documenting payment app use cases that will be significantly impacted if payment handler window becomes a 3P context. I hope this will allow us to make a pragmatic decision.

FWIW, I think a pragmatic decision is important. The web doesn't exist in an vacuum. The web will be out-competed by other platforms if it either fails flatly on privacy or if makes it impossible to build important user journeys. If I may just get a little philosophical, I feel payments is very important to the web, because the web's lack of a proper monetization model is part of what incentivized pervasive tracking. A secure, privacy-sensitive and low-friction payment primitive will allow content creators to monetize directly instead of relying on personalized ads.

The main difference is that the proposal can reject PaymentRequest.show before…

The concern here is that there doesn't seem to be a way that I can use the payment handler w/o giving it 1p storage. E.g. I have to give the context all or nothing, where 2y'd storage is in place to prevent putting users in this situation. Is there a way you can structure / order things where I can use the payment handler, w/o giving 1p storage?

Why should the payment handler be treated differently from a popup window, which has 1P storage?

The requestStorageAccess approach would seem to solve both use cases in my mind. By default I could save my self having to type in address info when reusing the same payment handler on the same site, and if wanted, the payment handler could use requestStorageAccess() to get the same privilege across all sites. Im not trying to be dense, but what use case am I missing?

The main use case I was worried about is using the same payment handler across all sites. I worry that if browser is required to prompt the user on every {website, payment app} combination, this will be a bad user experience. But I've never built a payment app buyflow, so maybe this is solvable. This is why I'd like to work with a real payment app to gain more nuanced understanding of the problems here. The documents I promised above should help me develop a more informed opinion.

Admittedly this idea needs more exploration. My initial thinking is that the Payment Request API is designed to serve a specific use case…

I would be interested in hearing more, but in general, I think you should start with the assumption that that any communication channel can ultimately be leveraged for arbitrary communication. Also note that any heuristic that depends on "did X match Y" or similar has likely already let some information pass and the cats already out the door…

Acknowledged.

To summarize, I think the best way to move this discussion forward is to do the following:

  1. I'll create a document to enumerate privacy attack vectors enabled by Payment Handler API
  2. I'll continue to work with payment apps we have relationship with to evaluate the impact of switching to 3P storage will have on existing use cases

Given that these tasks will take some time, one way we can limit the impact now is to move Payment Handler API behind Origin Trials [2]. Do you have a strong opinion about this?

[2] https://github.com/GoogleChrome/OriginTrials

@pes10k
Copy link
Author

pes10k commented Dec 10, 2019

Why should the payment handler be treated differently from a popup window, which has 1P storage?

This is not correct, popup (window.open) windows have partitioned storage, at least in the Safari implementation. I have not checked Firefox's or other's implementations.

I worry that if browser is required to prompt the user on every {website, payment app} combination

I appreciate that this might just be a difference of opinion, but being asked, once per {website, payment app} seem like a very low barrier to entry, especially given how sensitive the information is.

Given that these tasks will take some time, one way we can limit the impact now is to move Payment Handler API behind Origin Trials [2]. Do you have a strong opinion about this?

I would prefer that Google (or anyone else) not ship functionality on the web with known privacy holes, but I also realize that I don't have (nor probably should I have) any say on what Google does. I'm only here to make sure the spec winds up privacy-preserving.

One thing I would strongly emphasize though is that Chrome doesn't currently do any storage partitioning, doesn't implement Storage Access API, and has stated that it doesn't intend to ship it. So, Chrome users' experience with the API you might be putting behind origin trials may not (will not?) provide one-to-one feedback into the spec (which would presumably be implemented by folks who are, or will be, shipping Storage Access API).

@danyao
Copy link
Contributor

danyao commented Dec 11, 2019

Why should the payment handler be treated differently from a popup window, which has 1P storage?

This is not correct, popup (window.open) windows have partitioned storage, at least in the Safari implementation. I have not checked Firefox's or other's implementations.

This is news to me. Thanks for pointing it out. I'll look into Chrome's position on this one.

I worry that if browser is required to prompt the user on every {website, payment app} combination

I appreciate that this might just be a difference of opinion, but being asked, once per {website, payment app} seem like a very low barrier to entry, especially given how sensitive the information is.

Given that these tasks will take some time, one way we can limit the impact now is to move Payment Handler API behind Origin Trials [2]. Do you have a strong opinion about this?

I would prefer that Google (or anyone else) not ship functionality on the web with known privacy holes, but I also realize that I don't have (nor probably should I have) any say on what Google does. I'm only here to make sure the spec winds up privacy-preserving.

I appreciate the discussion.

One thing I would strongly emphasize though is that Chrome doesn't currently do any storage partitioning, doesn't implement Storage Access API, and has stated that it doesn't intend to ship it. So, Chrome users' experience with the API you might be putting behind origin trials may not (will not?) provide one-to-one feedback into the spec (which would presumably be implemented by folks who are, or will be, shipping Storage Access API).

I'm not following your point. The learnings I'm looking for are (i) the degree of reliance on cookie for a legitimate payment handler implementation (ii) user's ability to make sense of the security UX features of the payment handler window (e.g. URL, origin) and (iii) importance of explicit payment handler installation flows. I believe all of these are independent of whether Chrome implements Storage Access API, right?

@pes10k
Copy link
Author

pes10k commented Dec 11, 2019

I'm not following your point.

Could be that my point is totally wrong :) But I took you to mean that origin trials would give you feedback on whether 1p cookie jar is needed, whether storage access API prompts were appealing / tolerable / intolerable to users, etc, and since Chrome in some cases is, and in more cases soon, will be doing its own thing regarding 1p vs 3p and Storage Access API, I didn't know how "generalizable" the feedback from the origin trials would be. But if I'm misunderstanding or off base, please, disregard :)

@danyao
Copy link
Contributor

danyao commented Dec 11, 2019

I'm not following your point.

Could be that my point is totally wrong :) But I took you to mean that origin trials would give you feedback on whether 1p cookie jar is needed, whether storage access API prompts were appealing / tolerable / intolerable to users, etc, and since Chrome in some cases is, and in more cases soon, will be doing its own thing regarding 1p vs 3p and Storage Access API, I didn't know how "generalizable" the feedback from the origin trials would be. But if I'm misunderstanding or off base, please, disregard :)

Ah I see. You're right, the prompt friction of Chrome's specific UI will not be generalizable. I need to figure out what Chrome will be doing on Storage Access API.

I think knowing how critical is 1P cookie jar to payment flows, whether there are workable alternatives in a 3P context, and the general user perception of payment handler window may be transferrable lessons.

@jyasskin
Copy link
Member

I had a couple thoughts that I hope might be helpful:

  1. As @snyderp mentioned, the privacy-invasive bit isn't the act of loading two different first-party contexts at the same time; it's the fact that one can send a message that puts both parties' user IDs into the same JS environment at the same time. In the brave new world, users need to consent to that message.

  2. The core Payment Handler UI seems like a reasonable consent flow for this joining of first-party identities. That is:

    1. The user clicks something on the payee to start the flow.
    2. The browser shows the user a list of applicable payment methods, with whatever explanatory text it feels is appropriate. At worst, this can be the same text used to explain things within a requestStorageAccess() call.
    3. If the user clicks on a particular payment method, that's treated as consent to pass the payee's message (which might include a user ID) over to the payment provider.
    4. The user might then cancel out of the payment provider's flow, but they'd already consented to join identities before even entering that flow, and that can't be undone.
  3. To the extent that this isn't sufficient, but requestStorageAccess() in a "standard 3p context" does have the power to join user IDs, I think we can integrate that here. I don't know of a specification for "make the payment handler context a standard 3p content", and it seems complicated to have one notion that covers iframes, window.open()ed tabs, first-party contexts opened from a decorated link, etc., so I won't try to lean on that idea here. Instead, what if https://w3c.github.io/payment-handler/#handling-a-paymentrequestevent started with a call to requestStorageAccess() before it fires an event on the registered service worker? On success, the normal service worker can run and can open first-party windows. On failure, the next step probably has to be to open a payment-provider-provided URL in an iframe-like window that lets the user log in. Does that work privacy-wise? @johnwilander @Brandr0id (and not sure who owns this for Mozilla), does that make sense with the requestStorageAccess() API?

@pes10k
Copy link
Author

pes10k commented Dec 12, 2019

If I'm understanding the idea @jyasskin, I don't think it addresses the issue. It should be possible to use the same payment handler, on two different sites, without the payment handler automatically linking those two accounts (e.g. i want to use the company card on one site, and my personal card / persona / whatever on the other site).

Treating "request a payment event" as synonymous with "requestStorageAccess" when using the payment handler API would defeat the above possibility.

There is an opportunity here to enable convenient payments for users (Payment API win), w/o enabling account linking (privacy win). Treating the payment handler as a 1p context (or else get shunted to iframes / old way of doing things) boxes out that possibility.

Again, if im understanding the proposal right

@jyasskin
Copy link
Member

In (3) I was suggesting that "requestStorageAccess" be a sub-step of "request a payment". So, if a user chose to deny storage access, the payment flow would continue without any first-party cookies or storage. This would probably need to avoid the payment handler's service worker, so it might need some API changes, but I think those could be limited to providing a URL to be loaded as a third-party to let the user enter their payment information.

@danyao
Copy link
Contributor

danyao commented Dec 17, 2019

From discussion with @snyderp @marcoscaceres @aestes @rsolomakhin @ianbjacobs yesterday, I believe we reached the following consensus:

  • Payment handler window will only have 3P access to storage by default, unless user has consented previously.
  • User can consent to granting 1P storage access to a payment handler (identified by its origin) via a few new browser affordances:
    • (a) At payment handler install time: browser can offer user an option to opt-in, e.g. "would you like to allow wallet.example to access storage on all origins?" The default should be "no".
      • The consent granted here may be revoked after some period of inactivity with this payment handler, at the browser's discretion.
    • (b) During first use of a payment handler: browser may prompt user to opt-in if no previous consent exists.
    • (c) Periodically, during payment handler invocation: browser has the discretion to re-prompt user to opt-in based on signals such as the time of last consent and activity with the payment handler.

For both (b) and (c), Chrome, Firefox and Safari all indicated desire to reuse the same prompting strategy as the respective Storage Access API implementations.

Implications to the Payment Handler API:

Implications to payment handler developers:

  • None. The browser will treat a PaymentRequestEvent.openWindow() call as an implicit request for storage access, so developers don't have to explicitly call document.requestStorageAccess().
  • Browsers will fine-tune the UX of payment handler installation and prompting strategy to ensure no unnecessary friction is added to legitimate payment handlers.

Implication to users:

  • User may see more explicit prompts when a payment handler is installed and when they first use a payment handler. Browser vendors have discretion on the UX specifics. In general, we believe that if done right, the small friction of such "ceremony" is beneficial for establishing user trust.

Other noteworthy points discussed:

  • While payment handler API is not fundamentally different from a popup, @snyderp points out that Safari may be taking steps to make popups default to 3P context.
  • Firefox shared from their Storage Access API implementation experience that over-prompting has real UX harm. So some browser heuristic to avoid prompting user on every {payee, payment-handler} pair is probably essential.
  • The payment handler's Service Worker should probably be subjected to the same storage access restrictions as the visible payment handler window context. However, there are scenarios where the Service Worker is active without a visible web context (e.g. when hasEnrolledInstrument() is called or when a ServiceWorker chooses to handle show() without calling openWindow()). This needs a bit more thought to flesh out the details.

Next steps:

  • I'll flesh out the Service Worker implications
  • Start a pull request to incorporate the proposed changes

@pes10k
Copy link
Author

pes10k commented Dec 17, 2019

thanks @danyao !

Some other thoughts / questions:

  1. Is there a payer can opt to not prompt the user for 1p storage? I'm comfortable with the 'prompt-but-default-off' compromise reached above, but there should be a way for handlers to not prompt (e.g. only be used in 3p contexts), parallel to what would happen in an iframe that never called document.requestStorageAccess().
  2. What does blink / chrome plan on doing, since (I don't believe) there are any plans to ship storage access api on chrome?

@danyao
Copy link
Contributor

danyao commented Dec 17, 2019

thanks @danyao !

Some other thoughts / questions:

  1. Is there a payer can opt to not prompt the user for 1p storage? I'm comfortable with the 'prompt-but-default-off' compromise reached above, but there should be a way for handlers to not prompt (e.g. only be used in 3p contexts), parallel to what would happen in an iframe that never called document.requestStorageAccess().

Good question. My assumption is that identity is pretty crucial to payment apps so they would all want to use 1P storage, so the proposal above optimizes for that path. But it does seem to be a drawback if there are real payment handlers that want to opt-out of prompting. Maybe we can add an optional disableRequestStorageAccess argument to openWindow(). I'll keep this in mind when working with initial payment app developers. I think if necessary, it would be possible in the future to flip the default and require developers to call document.requestStorageAccess() directly.

  1. What does blink / chrome plan on doing, since (I don't believe) there are any plans to ship storage access api on chrome?

I don't have the full details on this. Your best bet is probably to ask on whatwg/html#3338. I'll make sure when it's available, Chrome's Payment Handler implementation will hook into that.

@plehegar plehegar added the privacy-tracker Group bringing to attention of Privacy, or tracked by the Privacy Group but not needing response. label Feb 10, 2020
@cyberphone
Copy link

If I read the spec correctly, the standard would allow the payment processor to track the user across pages that use the processor, since the processor would always have access to the same global storage, instead of different storage for each 1p it appears under

A payment processor accumulates information about merchants and users anyway.

Vetting is (IMO) the only way forward because a compromise will most likely leave everybody unhappy. Adding a set of "consents" which 99% of the user base do not understand the consequences of seems like a repeat of the pretty failed cookie consent thing.

FWIW, vetted native payment handlers like Apple Pay and Saturn are also domain agnostic which give them a clear edge over PaymentHandler.

@pes10k
Copy link
Author

pes10k commented Apr 8, 2020

I thought this issue was resolved? Is it still waiting for the spec to be updated? cc: @danyao

@ianbjacobs
Copy link
Contributor

Hi @pes10k,

The Working Group considered a number of proposed changes recently (at it's virtual meeting last week) including this one. There are a set of specification changes that I anticipate will be made, including related to this one.

Ian

@danyao
Copy link
Contributor

danyao commented Apr 8, 2020

Updating the spec has been blocked on the requestStorageAccess being spec'ed instead of just an open issue so there will be something to point to. But yeah, directionally I think we're going down this path. It's just a matter of ironing out the details. I'm syncing up with Chromium folks who're looking at 3P storage implementation next week to coordinate next steps.

@pes10k
Copy link
Author

pes10k commented Apr 8, 2020

I see, I'll wait to hear the result of that, but the outcome i thought we agreed to is doing more than just asking for consent; its designed to make sure that profile data isn't joined unexpectedly, etc. in a way thats compatible with dual keying storage and storage access api

@danyao
Copy link
Contributor

danyao commented Apr 8, 2020

I'll definitely keep you posted. This earlier comment is still the best capture of our agreement.

@cyberphone
Copy link

@danyao wrote "legitimate payment handlers".

This definition remains a problem. Assume that you want to create a wallet. That is, a PaymentHandler holding payment resources from multiple and independent payment providers. To succeed with that you need to (ab)use PaymentRequest for payment resource enrollments as well, in addition to heavily depend on 1p storage.

This is already a fact for native payment handlers like
https://cyberphone.github.io/doc/saturn/saturn-v3-presentation.pdf#page=4

@cyberphone
Copy link

The following example of a VRP (Variable Recurring Payment) for a Saturn-based phone-subscription request, highlights another limitation of the current approach to payment handlers. VRP is also a part of future Open Banking APIs.

{
  "amount": "360.00",
  "currency": "EUR",
  "nonDirectPayment": {
    "type": "RECURRING",
    "interval": "MONTHLY",
    "fixed": false,
    "expires": "2022-04-13T00:00:00Z"
  },
  "referenceId": "754329",
  "timeStamp": "2020-04-12T06:04:12Z",
  "expires": "2020-04-12T06:35:00Z"
}

To cope with this scenario, Saturn only uses PaymentRequest as a bridging mechanism.

Of course you can deal with VRP outside of PaymentRequest but then you lose the ability creating a [more] complete User authorization object and associated UI. The € 360 is the upfront fee, not the total so the finalized authorization may also be subjected to a User credit score evaluation.

This specification talks about "fake" payments so I'm in "good company" 😇
https://github.com/adrianhopebailie/modal-window/blob/master/explainer.md#payment-handler-api

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
privacy-tracker Group bringing to attention of Privacy, or tracked by the Privacy Group but not needing response.
Projects
None yet
Development

No branches or pull requests

7 participants