w3c / secure-payment-confirmation

Secure Payment Confirmation (SPC)
https://w3c.github.io/secure-payment-confirmation/
Other
114 stars 40 forks source link

Should SPC be invokable outside of a PaymentRequest flow? #65

Open stephenmcgruer opened 3 years ago

stephenmcgruer commented 3 years ago

Ian and I were chatting today and discovered that we had very different mental models about when SPC authentication is invokable; it seems worthwhile to hash these out and come to a conclusion that we can document (as part of the Scope document?).

Some casual definitions:

Given these definitions, I believe that SPC authentication should be invokable in both informal and web-api payment contexts. Do others agree?

Note that if SPC is invokable in informal payment contexts, it is invokable anywhere on the web as the browser cannot tell the difference. It should always require a user gesture, imo, and the browser UX that will be shown should always state a payment context.

stephenmcgruer commented 3 years ago

For completeness: SPC as described in the explainer is only usable in an informal payment context, not a web-api context. Although explainer-SPC uses the PaymentRequest API, it is not part of a PaymentRequest flow; it's just piggy-backing on the existing infrastructure. The explainer version of SPC can't be used inside a PaymentRequest flow (e.g. a web PaymentHandler), because PaymentRequests cannot be nested (step 8 of show() - https://w3c.github.io/payment-request/#show-method).

cyberphone commented 3 years ago

@stephenmcgruer Since you requested input on a pretty fundamental issue, may I as an external comment on this?

IMO, SPC is (or should at least be), a browser-built-in payment-handler, activated by the existing PaymentRequest API for usage in payment scenarios. Personally, I would limit the scope even further by making crypto = FIDO. Going outside of this already quite challenging scope would IMO be unwise (unless it is supported by peer-reviewed, fairly complete specifications, and thoroughly tested code).

Other solutions and scenarios can presumably be supported by existing Web technologies.

In case you want to discuss this further, please use my email: anders.rundgren.net@gmail.com.

@rsolomakhin @nickburris @btidor-stripe @jcjones

SensibleWood commented 3 years ago

+1 on @cyberphone comments. Anything that is 1) not tied to the Payment Request API and 2) not FIDO has the net effect of making of the scope explode IMHO. The neat thing about the original SPC proposal was the the use case was clear, unequivocal and single-minded in its purpose. FIDO2 + Payment Request API === a chance of success and adoption.

cyberphone commented 3 years ago

A closely related issue... If SPC becomes a "security framework" that only kicks in when required (like 3DS), it won't become a brand. This departs from essentially every other system out there, from PayPal to SRC: https://www.emvco.com/emv_insights_post/introducing-the-click-to-pay-icon/

This is how I envision SPC could appear on a merchant checkout page, here supporting three different payment networks: spc

For Open Banking implementations, the name of the payment network would probably be something like "Pay with your Bank" .

adrianhopebailie commented 3 years ago

SPC is not an "API" it is a function.

It should only be available inside the formal PR API call for the reasons specified in https://github.com/w3c/secure-payment-confirmation/issues/56#issuecomment-832537029

I wouldn't read much into the API shape as defined in the explainer. @danyao and I agreed early on that the design for the experiments was simply a "quick and dirty" to get some data.

My mental model for PR API is that it is simply the way a website invokes a payment context. We have already made some big simplifying changes to PR API through https://github.com/w3c/payment-request/pull/955 to make it more flexible. I don't believe there is a concept of a "Payment Request flow" since the browser is no longer collecting data on behalf of the website.

I imagine functions available inside the payment context being:

The specific functions available and invoked inside the payment context will differ depending on how the PR was constructed. E.g.

  1. If a website already knows which payment credential will be used to authenticate the payment it might call PR API and pass the credential with the request but not specify a list of payment methods (similar to the API design in the explainer)
  2. If a website has a list of payment credentials that could be used it could call PR API and pass all of them to PR API and the browser will prompt the user to choose a payment instrument linked to one of them (assuming more than 1 has been enrolled previously).
  3. If a website has a list of payment methods it accepts and is unsure if any payment credentials are already enrolled it can specify the list of payment methods and the browser will prompt the user to select a payment instrument matching one of the payment methods.
  4. Etc.

I think we should not get too far ahead in trying to design the API shape for SPC (or start assuming it won't be part of PR API) until we have ironed out the scope and requirements a little more.

@cyberphone SPC is NOT intended to be a brand. It is an authentication and confirmation framework that can be leveraged by existing payment methods. The goal is to standardise the primitives for authN and confirmation so that this is possible.

stephenmcgruer commented 3 years ago

Thanks @adrianhopebailie

I believe you and I agree, and are just using slightly different meanings for terminology. Everything in your post I agree with except the 'theory' parts (what constitutes a payment context :D).

I have trouble explaining things here without relying on some concrete proposal, to be honest. The core of this issue was that I don't want merchants to have to switch to Payments-related web-APIs for anything other than SPC, to use SPC.

That is, if a merchant, Alice, has a HTML-based guest checkout form setup that's working for her today (so no Payments web-APIs there), she should be able to integrate SPC to get strong user authentication without needing to adopt any other Payment APIs (such as, if you'll excuse the concrete example, the use of a PaymentHandler like basic-card, Apple Pay, or Google Pay).

cyberphone commented 3 years ago

@adrianhopebailie writes

SPC is NOT intended to be a brand. It is an authentication and confirmation framework that can be leveraged by existing payment methods.

This excludes a wallet which @stephenmcgruer has in private communication mentioned as likely to be a part of SPC. Does the world really need yet another framework? Wouldn't a concrete system be easier to define, deploy, and market?

A framework will be facing a virtual army of quite popular and useful mobile payment and banking applications. A Standardized, Vendor-independent, Convenient, Secure, Universal, and [potentially] Always Available alternative is (standards-wise) probably the only thing that could make a real impact in a market which currently have to cope with an ever-increasing number of "innovative" payment solutions.

ianbjacobs commented 3 years ago

Hi all, We discussed this at our 27 May teleconference: https://www.w3.org/2021/05/27-wpwg-minutes#t03

(No strong feelings were expressed there.)

adrianhopebailie commented 3 years ago

@stephenmcgruer I think we are on the same page but perhaps have different ideas about HOW someone could use PR API, for example if all they want is SPC.

You said (and I agree with this):

if a merchant, Alice, has a HTML-based guest checkout form setup that's working for her today (so no Payments web-APIs there), she should be able to integrate SPC to get strong user authentication without needing to adopt any other Payment APIs (such as, if you'll excuse the concrete example, the use of a PaymentHandler like basic-card, Apple Pay, or Google Pay).

My expectation is that in this case Alice would create a new PR object but would not specify any payment methods (i.e. telling the browser she is not interested in invoking browser facilitated instrument selection or any third-party apps). She WOULD set a flag, or provide some input data (such as a list of credential IDs) that indicates she wishes to do SPC if it is available.

This creates a clean DX where any functions related to payment are part of PR API.

adrianhopebailie commented 3 years ago

To elaborate a little on the DX and UX I have in mind here.

When a merchant invokes a new payment flow they may have very little data already about who the user is and how they wish to pay (e.g. guest checkout) or they may have a lot of this data already (instruments, user id, credential ids etc).

They should invoke the PR API, providing the data they do have and indicating to the browser (via the options argument) which browser-facilitated steps in the flow they wish to enable.

The flow, at a high level, works as follows, where the browser MAY facilitate any or none of the steps:

  1. Identify the payment instrument to use
  2. Authenticate the user
  3. Confirm the payment details
  4. Authorise the payment

The flow is a 3-party flow involving the merchant, the RP, and the user with the browser as the mediator between them.

The flow is invoked by the merchant calling PR API show() and control is passed to the other parties by the browser as appropriate based on:

  1. The data provided by the merchant
  2. The available payment handlers installed
  3. The available payment instruments installed with associated SPC credentials

Control is passed to the merchant via events on the PR object, to the RP via events in the RP's payment handler and to the user via UI rendered by the browser.

My expectation is that there will be 3 ways to invoke SPC:

  1. By the merchant by passing the required data directly into PR constructor
  2. By the merchant inside an "instrumentSelected" event emitted by the PR object
  3. By the RP (via an API exposed inside a payment handler, or via PR API from inside an iframe the same as the merchant methods above)

Example of 1:

  let details = {
    total: {label: 'Total', amount: {currency: 'USD', value: '55.00'}},
    secureConfirmation: {
        credentialIds,
        networkData
  };
  let options = {requestSecurePaymentConfirmation: true};
  // Empty paymentMethods means skip instrument or payment handler selection
  // Using PR constructor still gives us the structured payment details to use in confirmation
  let request = new PaymentRequest([], details, options); 

Example of 2:

let request = new PaymentRequest(methods, details, options); 

// Merchant binds to instrument selection event so browser doesn't attempt to invoke payment handlers
// Instead user will be prompted to select a payment instrument from installed instruments filtered by supported payment methods
request.addEventListener('instrumentselected', async function(evt) {
    const networkData = await getChallenge() 
    // Do SPC using the selected instrument and the challenge from the RP
    const response = await evt.confirmPayment(networkData)
    await response.complete('success')
});

Obviously this is very speculative but it provides some illustration of the direction I was imagining. Does it make sense?

rsolomakhin commented 3 years ago

HI @adrianhopebailie,

I would prefer to keep the API as simple as possible for a number of reasons. One of the things that I'd like to avoid is instrument selection in the browser UI, at least for now. That means the instrumentselected event may not be a good fit.

Distinguishing between the merchant and the RP and communicating with them in different ways also appears to introduce extra complexity without a well defined benefit. Can the API communicate only to the current web page?

As for "Example 1", it seems counterintuitive to pass in 0 supported methods, but then add requestSecurePaymentConfirmation as an option.

What do you think about an API shape like this:

new PaymentRequest(
    [{
      supportedMethods: "secure-payment-confirmation",
      data: {credentialIds, challenge, timeout},
    }],
    details);

Cheers, Rouslan

ianbjacobs commented 3 years ago

@rsolomakhin,

If SPC can be called outside of PR API, then I suggest that we not follow the pattern of your example. SPC is not a payment method. It is an authentication approach. It is not a peer of GooglePay, ApplePay, SamsungPay, SRC, etc. It should be usable by them during PR API or by a payment app. It should also be usable for vanilla form-based payment flows.

rsolomakhin commented 3 years ago

It should be usable by them during PR API or by a payment app

Could you provide more detail on how that would be accomplished?

It should also be usable for vanilla form-based payment flows.

That's what new PaymentRequest([{supportedMethods: "secure-payment-confirmation"... accomplishes, right?

ianbjacobs commented 3 years ago

That's what new PaymentRequest([{supportedMethods: "secure-payment-confirmation"... accomplishes, right?

Yes, except this isn't a payment request. In my mind:

So I would not call "new PaymentRequest()" but "new SecurePaymentConfirmation()"

rsolomakhin commented 3 years ago

SPC can also be viewed as "Get me some payment authentication credentials" 😉

adrianhopebailie commented 3 years ago

I've mulled this over a bit and I can see the argument for non-PR API invocation of SPC.

Assuming, based on the requirements, that the SPC Credential is some implementation of the Credential interface as defined in the Credential Management API.

It seems sensible (as suggested by @tblachowicz in https://github.com/w3c/secure-payment-confirmation/issues/56) that a website should be able to simply call navigator.credentials.get(...) to invoke SPC. If the request specifies that the credential type is a payment credential then that seems a strong enough signal to the browser that this is a payment context.

rsolomakhin commented 3 years ago

Very interesting, @adrianhopebailie!

I can see the argument for non-PR API invocation of SPC

Could you help to articulate this argument succinctly please? I am wondering whether it is a gut feel / preference derived from your extensive experience in the industry (it's great to have your expertise! 👍 ) and whether there are clear trade-offs "for" and "against" the different approaches.

a website should be able to simply call navigator.credentials.get(...) to invoke SPC

Is the suggestion to add a special case for payments in navigator.credentials.get(...) that has its own UI and also allows execution by 3rd parties (i.e., merchant.com or psp.com creating a signature for rp.com)?

There have been some discussions of re-using PublicKeyCredential for SPC (instead of creating a new type of PaymentCredential) and passing the instrument icon and name at payment time instead of at enrollment time. Is this a suggestion that these parameters be passed in to navigator.credentials.get(...)?

ianbjacobs commented 3 years ago

My understanding is that the answer to this question is:

Goosth commented 3 years ago

SPC brings 3 things: Cryptographic proof, Payment specific display and Cross Domain ability.

From @adrianhopebailie's comments it seems that navigator.credentials.get(...) will be able to provide a payment specific display. By design it already offers the cryptographic proof.

The uncertainty for me is around the cross-domain access. Not sure if we would be able to manage that in navigator.credentials.get(...). As an account provider we would gladly use navigator.credentials.get(...) since we're in the correct domain. But what about merchant's need to activate this from their domain? That's a payment-handler superpower... and not sure it can, or should be transferred to the Credential Management API?

ianbjacobs commented 2 years ago

Labeled after-v1 based on 3 March 2022 WG discussion https://www.w3.org/2022/03/03-wpwg-minutes