Closed caraitto closed 2 years ago
would the credential creation only happen after the browser payment UX flow is completed by the user
The browser payment UX flow is not involved in registering a new credential. As it stands right now, registering a credential can be done without any browser UX, just like in WebAuthn.
The browser payment UX flow is used when the website is "getting an assertion", i.e., asking for a signature over payment data, using an already existing credential. That's when the browser shows its own payment UX flow.
The browser payment UX ... can't be faked
A webpage can make a fake browser payment UX that 90% of users will not notice is fake.
The security of SPC comes more from the fact that the webpage is unable to modify the "clientDataJSON"
values that the authenticator signs cryptographically. If the webpage calls navigator.credentials.get()
for some public key credential, then "clientDataJSON.type"
will be "webauthn.get"
, whereas SPC API call will return a "clientDataJSON.type"
of "payment.get"
, among other differences.
a page couldn't "for example - overlay a transparent iframe on-top of a legitimate button" on top of the payment UX
That is correct.
The security of SPC comes more from the fact that the webpage is unable to modify the
"clientDataJSON"
values that the authenticator signs cryptographically. If the webpage callsnavigator.credentials.get()
for some public key credential, then"clientDataJSON.type"
will be"webauthn.get"
, whereas SPC API call will return a"clientDataJSON.type"
of"payment.get"
, among other differences.
My threat concern isn't so much about security, as cross-site identifiability -- I'm trying to determine if this API could be used to build an identifier that can be read by multiple (possibly colluding) origins such that this identifier could be used as a "joining key", linking identities from one site to another.
would the credential creation only happen after the browser payment UX flow is completed by the user
The browser payment UX flow is not involved in registering a new credential. As it stands right now, registering a credential can be done without any browser UX, just like in WebAuthn.
Since it sounds like this credential can be created in a third-party iframe -- can this credential be read by the page (somehow sent to the page's server) after creation? If so, in these 2 scenarios:
1: top: foo.com iframe: bar.com
2: top: baz.com iframe: bar.com
...does bar.com get to read the same credential in both cases? If so, it sounds like a cross-site tracking vector? Requiring user activation to create the credential helps some, but sometimes the page can coax the user with misleading UX to harvest gestures. The issue still exists if the user makes a payment, but at least they're placing some implicit trust in the site by making a payment.
If it's not possible for bar.com to read the credential until the payment completes (i.e., it's read-only stored in the browser until the payment is approved by the user), this would mitigate the concern.
The browser payment UX ... can't be faked
A webpage can make a fake browser payment UX that 90% of users will not notice is fake.
Correct -- the thought was that if the real payment UI was required to create the credential, a fake payment UI implemented in HTML/CSS/JS wouldn't be able to create the credential, even if the user was tricked into believing that the UI is the real browser UI and not a fake.
But, credential creation without requiring the payment UI should be OK, as long as reading the credential requires the payment UI flow to complete.
I think that there's some confusion in this issue over registration (a one-time process that does not necessarily involve a payment, and which results in a created WebAuthn credential) and authentication (a many-time process that does involve a payment, and which utilizes an already-created WebAuthn credential). It may be worth reading the SPC introduction section if not already done so.
In terms of the foo.com
, baz.com
, bar.com
example: if a credential already exists for bar.com
(the child), then being able to read such a credential in a 3p iframe is possible in WebAuthn today: one can call navigator.credential.get()
in an iframe, without user activation, if the parent frame has given the iframe the publickey-credentials-get
policy (https://www.w3.org/TR/webauthn-2/#sctn-permissions-policy).
SPC inherits this behavior, so nothing is new on that side. (In fact, as noted, we throw up a bunch of payments UX that probably makes the read even worse, and we require a user activation).
But, credential creation without requiring the payment UI should be OK, as long as reading the credential requires the payment UI flow to complete.
Confirming the credentials existence does require the user to agree to the payment UX (and then complete the subsequent WebAuthn UX and interaction too). Again, note that WebAuthn today allows read in a 3p iframe without SPC's UX or requirement for user activation.
What is relevant to think about here is the registration part. SPC allows a site to create a credential in a 3p iframe, whereas in WebAuthn the user would have to be redirected to or otherwise visit the page (bar.com
in the above example). This is discussed in the explainer as noted in the OP, and also in a bit more detail in the spec: https://w3c.github.io/secure-payment-confirmation/#sctn-security-cross-origin-registration
This is definitely a feasible privacy attack, albeit we note it requires either cooperation from the main frame (in which case one is somewhat out of luck anyway) or script injection into the main frame. There is a little bit of defense in the WebAuthn creation UX that will be shown, which would identify to the user that the credential is for bar.com
not foo.com
, but we acknowledge that users don't usually read such UX in enough detail anyway.
Thanks for some additional background -- I'm still investigating the existing WebAuthn tracking potential.
Just wanted to clarify:
requires either cooperation from the main frame (in which case one is somewhat out of luck anyway)
Our threat model assumes that the main frame and subframe can collude.
Maybe it would be good to schedule a meeting? I'll reach out internally.
@caraitto, @rsolomakhin , and I met yesterday to discuss this issue. The main outcomes were that (and please correct me if I'm wrong here, @caraitto ):
Let's discuss the user-activation suggestion at the next task force meeting.
Thanks @stephenmcgruer -- this sounds like a good summary. I think it would be good to consider adding an activation requirement.
To give a direction for the upcoming TPAC discussion on this issue: I propose that we adopt requiring a user activation for creation of an SPC credential.
Tracking related discussion in WebAuthn https://github.com/w3c/webauthn/issues/1293
Coming back to this issue (which was not discussed at TPAC). I think for user protection, we should require user-activation for credential creation when the payment extension is specified (e.g., for SPC-enabled credentials). To this end, I have created a draft PR that would enforce this - https://github.com/w3c/secure-payment-confirmation/pull/178
There are two main considerations here when thinking about landing this (beyond the security/privacy improvement):
For (1), I believe that all known users of SPC currently have a user-activation anyway in their registration flows, though we should check that.
For (2), I believe that this extra step is necessary here because we allow registration in a cross-origin iframe, which is more dangerous than WebAuthn's case. Also, requiring it is more stringent than not, so if in the future we wanted to 'walk it back' and change our minds, it would be backwards compatible to do so.
@jcemer-stripe, @ACathelin, could you confirm that your flows include user activation? Thanks!
Yes, our current flow includes user activation. We aren't prompting enrollment before user acknowledging it.
Adding @Eric-Alvarez to see if we can hear Adyen perspective.
@caraitto - we've now merged a PR to add a user-activation requirement for credential creation in a cross-origin iframe (see #178 ), and plan to ship the change in M103 (https://groups.google.com/u/1/a/chromium.org/g/blink-dev/c/GSoWLFb_jF0). Can you confirm that this issue is resolved to your satisfaction?
Thanks, LGTM.
Your new blink-dev I2S will get picked up by the next reviewer in our rotation, which it looks like won't be me, but they should see the activation requirement introduced by your PR.
Thanks caraitto, closing this issue then as the spec change has landed :).
https://github.com/w3c/secure-payment-confirmation/blob/main/explainer.md#enrollment-in-cross-origin-iframes mentions that "if site A embeds an iframe from site B, with the "payment" policy set, then site B may initiate a credential creation for site B within that iframe", with a proposed mitigation of requiring transient user activation.
For secure payment confirmation specifically, would the credential creation only happen after the browser payment UX flow is completed by the user? The browser payment UX seems stronger than mere user activation, since it's controlled by the browser and can't be faked (for instance, a page couldn't "for example - overlay a transparent iframe on-top of a legitimate button" on top of the payment UX for the purpose of cross-site tracking). Is there something I'm missing?