Giter Site home page Giter Site logo

w3c / secure-payment-confirmation Goto Github PK

View Code? Open in Web Editor NEW
103.0 33.0 48.0 3.74 MB

Secure Payment Confirmation (SPC)

Home Page: https://w3c.github.io/secure-payment-confirmation/

License: Other

Makefile 0.82% Bikeshed 99.18%
webauthn payment-request payment-handler 3ds public-key

secure-payment-confirmation's Introduction

Secure Payment Confirmation

Secure Payment Confirmation (SPC) is a Web API to support streamlined authentication during a payment transaction. It is designed to scale authentication across merchants, to be used within a wide range of authentication protocols, and to produce cryptographic evidence that the user has confirmed transaction details. The W3C Web Payments Working Group is developing SPC.

Links:

Screenshot

FAQ

Q. Who can validate the SPC response besides the actual Relying Party (RP)?

An SPC challenge bundles transaction details with transaction-specific dynamic data from the Relying Party. An SPC response includes a signature over that challenge. Validation in SPC refers to the verification of that signature using the credential public key. A Relying Party can choose to share the credential public key with another party (e.g., a card network or payment service provider) via out-of-band communication to enable that party to validate the SPC assertion.

Acknowledgements

Contributors:

  • Adrian Hope-Bailie (Coil)
  • Benjamin Tidor (Stripe)
  • Danyao Wang (Google)
  • Christiaan Brand (Google)
  • Rouslan Solomakhin (Google)
  • Nick Burris (Google)
  • Gerhard Oosthuizen (Entersekt)

secure-payment-confirmation's People

Contributors

adrianhopebailie avatar christiaanbrand avatar danyao avatar goosth avatar ianbjacobs avatar jcjones avatar nickburris avatar rsolomakhin avatar samuelweiler avatar stephenmcgruer avatar tblachowicz avatar tidoust avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

secure-payment-confirmation's Issues

Unable to "decipher" sequence diagram

When looking at https://github.com/rsolomakhin/secure-payment-confirmation/blob/master/sequence-diagrams/SecurePaymentConfirmation-Pilot-Checkout.png I fail linking it to 3DS. In my understanding, 3DS is a separate (additional) card-holder authentication process performed before the actual payment process is initiated.

In the last part of the mentioned sequence diagram it seems that the ACS is the same as a payment initiation end-point. That is not how the existing 3DS ecosystem works.

Am I missing something here?

I would consider making a less crammed version of sequence diagram where each step is numbered, making it possible to put explanatory data in text outside of the diagram.

@danyao

Is an issuer hosted payment handler necessary for secure-payment-confirmation flow?

In Secure Payment Confirmation, if authentication fails, who should be responsible for showing the fallback URL inside a Secure Modal Window (a.k.a. payment handler window)?

Option 1 is browser. This is the simplest for merchant/PSP and issuer as serving static web pages are much simpler than hosting service workers. However, there are challenging open questions that need to be thought through:

  • Who controls the life cycle of the Secure Modal Window?
  • How does the web content inside the Secure Modal Window communicate with the invoking context (i.e. merchant/PSP)?
  • What are the privacy and security threat models of Secure Modal Window?

Option 2 is an issuer-hosted payment handler. This payment handler can be installed when the issuer enrolls a PaymentCredential and is bound to the newly created credential. Then during checkout time, the browser passes the authentication result (pass or fail) to the issuer payment handler via an extension to the PaymentHandlerEvent, and the service worker can choose to fall back in an open window or not.

The main benefit of option 2 is that it fits well within the existing web payments architecture, where the security and privacy models are well understood.

Provide support for Out of Band Authentication to a secondary device

We should probably consider other flows defined inside 3DS 2.0.
Consider a situation where the current device has not yet been setup/registered for WebAuthn, but another device linked to this user has have been setup. This is very probable in a Guest shopping scenario.

Out of Band authentication allows the browser to reach out a second device (typically a mobile phone the user carries with them) where the transaction is approved.

Note that we're not talking about using OTP's here, but rather the ability to reach out to a second device and activate the Authentication (e.g. a WebAuthn Platform Authenticator) on that device. If this is is something we can design in should achieve much higher adoption, since a user will not have to have their Fido Authenticator setup on all devices that they own.

Who is the actual RP?

In the original 3DS setup the ACS is used to assure the Merchant/Card network that the card -holder is authentic. As far as I recall, the result of this authentication is not brought back to the Issuer during the actual transaction request since that would involve changes in the core payment protocol as well as require interaction with the ACS.

Because the current SPC flow diagrams are pretty hard to follow, I'm unable to tell if this part has changed or not.

If this has not changed, I wouldn't characterize the Issuer as the RP.

Using CredentialsContainer.get() instead of Payment Request API

The initial proposal assumed that Payment Request API (PR API) should be used to trigger the SPC flow. The client code would use PR API providing the payment method as predefined value e.g. "secure-payment-confirmation" and the necessary parameters such as total amount, cryptographic nonce, fallback URL, and so on.

Alternatively, the same SPC flow could be triggered simply by invoking the Credential Management API CredentialsContianer.get() method as it happens for other types of credentials. Example SPRC request:

navigator.credentials. get({
  spc:{
    credentialIds: 'array of credential identifiers',
    amount: 'amount w/currency',
    nonce: 'server-side generated cryptographic nonce',
    fallbackUrl: 'URL of the fallback page',
    timeout: 'timeout for the request'
})

Similarly, the SPCCredential or PaymentCredential would extend the Credential interface to be consistent with the Credential Management API.

Are there any clear benefits of using Payment Request API instead of Credential Management API?

payment Method versus payment Instruments

From the samples it appears that there is just a payment method and no payment instruments.

If this is correct, the universality of this system will be unnecessary limited.

Encrypt SPC Credential Identifiers in authentication flows to increase privacy

@Goosth and I believe others have pointed out that it would be great to reduce tracking risk by not reusing the same SPC Credential IDs across transactions. Here is an idea:

  1. At enrollment, the relying party provides a public key in addition to other data (e.g., display
    information, relying party ID). The relying party associates this public key with the SPC Credential
    Identifier they get back through enrollment.

  2. At transaction time, the relying party prepares input for SPC (either for someone like a PSP or their
    own usage) by encrypting a hash of an SPC Credential ID along with a time stamp (for example).
    The relying party ID and encrypted blob are provided as input to SPC.

  3. The browser follows this algorithm (or similar):

    • Create a list of all SPC Credentials that have the relying party ID. If none, silently fail.
    • For each SPC Credential, get the stored public key. Use it to decrypt the encrypted blob. If the
      SPC Credential ID in the blob matches this SPC Credential's identifier, proceed to authenticate
      based on this SPC Credential.
    • If nothing matches, silently fail.

This is a rough idea; I look forward to hearing suggestions to make it realistic and effective.

Include a field for the RP to provide routing information

Reposting a question from @ianbjacobs:

Should we include a field for the RP to provide routing information, rather than assuming that the instrument id will carry the routing information in all cases? The field might be optional. But, for example, it would easily map to systems like ACH (routing number, account number).

Does the API support timeout?

Raised in discussion with @Goosth:

  • The transaction confirmation dialog opens
  • The user does not authenticate or cancel within some time frame.

What happens? Are there timeout parameters?

Are Client-side Discoverable Credentials (aka Resident Keys) off the table in this proposal?

Just wondering what the approach is for Client-side Discoverable Credentials is? (Just for ease, here's their definition).

From the examples the querying function appears to replace it, but that has implications for the inherent advantages of discovery, especially in usability i.e. the RP in this context (the Merchant - not the origin) will "always" have to "know" the Credential identifier. From the perspective of user experience it would great to allow a "natural" selection of the credential at the Authenticator, with some visual prompts for the user.

Leveraging the discoverable credentials approach could allow for the actual payment instrument - lets say it's a payment card - to be stored within the Authenticator using a Level 2 mechanism such as credential properties. This would allow for a belt-and-braces approach where the Authenticator delivers both the authentication event and the secured instrument data.

Instrument ID should never leave the payment handler or browser

Reposting a question from @ianbjacobs:

The instrument id is minted by the relying party. Could we design this so that the instrument id never leaves the payment handler or browser?

For example, if the browser returned a hash of the instrument id and the merchant origin, then the merchant could send that hash (and their origin) to the RP and the RP could figure out the underlying instrument id. I realize that may be cumbersome for the RP (e.g., if they have to process a large number of instrument ids). I mention it here as an example of trying to figure out a way to not reveal the instrument id to the PR API caller.

The instrument id visibility problem seems relevant with or without payment handlers.

Allow enrollment outside of transaction flow

I would like to hear from people whether it is important to allow credential enrollment outside a Payment Request flow. For example, I visit my payment provider (BobPay) and enroll my authenticator for a future SPC payment.

Test build

Is there a Chrome/Edge/Firefox build that I can play with to test that out yet?

Consider EMV for the Web

I haven't "deciphered" the entire spec but the following lines caught my eyes:

While the credential ID may be used as a tracker to correlate a user across origins, an origin (e.g. a merchant) needs to already have access to the credential ID in order to invoke the new API. A merchant also already has a more powerful identifier, i.e. the raw credit card number the user provided, that it used to exchange to the credential ID via trusted server side integration with the issuing bank.

Creating a new system that needs card numbers in clear outside of the RP/Bank environment seems somewhat short-sighted and may even be in conflict with GDPR. Since WebAuthn was built for the Web, wouldn't it be reasonable using Web-methods to overcome deficiencies that stems from technology that was created 25 years ago?

This presentation outlines such a system: https://www.youtube.com/watch?v=OWn8sg7Oy3I&t=306s

That is, payment credentials are also fitted with

  • A URL to the issuing RP/Bank. This replaces the card number routing system and probably works for just about any account based system including IBAN
  • An issuer-specific (non-personal) Encryption Key

making authorizations only reveal which bank the user have.

The hashing mentioned in the presentation has recently got a suitable solution that is 100% JavaScript compatible: https://www.rfc-editor.org/rfc/rfc8785.html

This is effectively a souped-up EMV adapted for the Web. EMV is more "protocol-efficient" than 3DS-like concepts.

Browser-wise I believe this is quite simple to achieve. Backend-wise not so. The ability to support IBAN & friends is probably a necessity to get traction. Note that such systems do not provide any "fallbacks" and such.

Should SPC be invokable outside of a PaymentRequest flow?

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:

  • A payment context: a state in which the user views themself as in the process of a financial transaction (often referred to as being in a 'payment flow'). Divided into:
    • An informal payment context: a payment context in which the flow is not visible to the browser (e.g. a checkout flow implemented with generic web APIs).
    • A web-api payment context: a payment context in which the flow is happening via payment-related web APIs (e.g. inside of PaymentRequest.show(), such as a web-based PaymentHandler) and as such is visible to the browser.

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.

What are requirements when more than one SPC credential matches?

Based on some questions by @Goosth:

When more than once SPC credential matches, what requirements are there, and what should be left to browser innovation?

For example:

  • We should not tell the browser how to display multiple credentials for the user to select one. We might in the API indicate factually that when more than one credential matches the user agent prompts the user to choose one.
  • I think it may be an optimization (and thus not a requirement) for the browser to support user configuration of a default.

On the other hand, it might be a requirement for the browser to try to match the requirements in the order specified in the input to the API. This would allow the RP to express preferences, and this could be one way for the RP to say "I want you to go for frictionless first, then low friction."

Enrollment should not interrupt payment response

cc @btidor-stripe

I want to capture here a request I have heard in discussions about the Stripe pilot:

  1. The user is authenticated with 3DS OTP
  2. The merchant should get paid at that point
  3. Optional SPC enrollment then happens
  4. The merchant shows a "Done!" page

If Step two implies that Payment Request terminates (and the merchant receives Response data), how would SPC enrollment happen?

Linking PaymentCredentialInstrument with PaymentInstrument/Payment Handler

In the proposal, the new PaymentCredentialInstrument is not linked with enrolled PaymentInstruments associated with the Payment Handler. I think it's worth considering linking the two types of instruments together, especially to support the combined flow where the instrument is selected and then end-user authenticated.

Suggestion to enable Frictionless Flows

Introduction

Weโ€™ve heard a lot about โ€˜frictionless authenticationโ€™ at TPAC 2020 regarding SPC. Itโ€™s considered an essential requirement for merchant adoption in certain markets, due to the historic pain experienced with issuer challenges. It's a key benefit promised for 3D Secure 2.

This post is an suggestion on how we could utilize the SPC public-key-credential to payment-card linking mechanism to enable frictionless authentication. The idea is inspired by the Credential API picture in the presentation given at the TPAC WPWG sessions (slide 14, thanks @danyao).

SPC was implemented by adding a new credential type (PaymentCredential) to the Credential Management API. This new PaymentCredential type includes a list of other trusted public-key credentials; which today consist of a set of WebAuthn Keys (called PublicKeyCredential in the Credential Management API).

Proposal

What if we supported an additional type of credential that can be used frictionlessly. Ideally this would also be a public-private keypair, similar to Webautnโ€™s PublicKeyCredential. This credential would have the following attributes:

  • a Public-Private keypair, both created in the browser instance and where the private key is never exposed to anything.
  • The ability to sign a challenge without requiring user-action.

This attribute would then be able to show a certain browser presence during a transaction.
This functionality actually already exists in WebCrypto API. The object created is called CryptoKey.
In CredentialManagement, we could call this a CryptoKeyCredential. The CredentialManagement API would bring the ability to get user-consent when this is created. And it would then be stored and retrievable in a similar way to other Credentials.

Our PaymentCredential would then be able to link into both PublicKeyCredentials and CryptoKeyCredentials (via existingCredential).

Enabling this flow.

So, if this was in place and an issuer wanted to enable frictionless flows it would just need to do the following:

Enroll

  • Create a new CryptoKeyCredential on a trusted browser (getting user consent that they trust this browser)
  • Link this new CryptoKeyCredential to a PaymentCredential, potentially also with a set of PublicKeyCredentials thatโ€™s also trusted by this user

Checkout

  • When the issuer needs to return a list of trusted credentials, they can indicate the option of a frictionless flow (based on risk), by returning CryptoKeyCredentials in the list returned to the merchant.
  • When SPC is initiated, it would first check if any frictionless CryptoKeyCredentials returned are present on the browser, and if they are, they could be used as signing proof of the transaction. If none are present it would try the WebAuthnCredentials, and failing that fallback to the fallback URL.

If I understand the SPC API and implementation correctly, this would require virtually no change to the SPC interface. Just the ability to store a new credential type in the browser. And in return, we would be able to offer frictionless SPC consent.

Would be great to explain and explore this further in future WPWG session.

Specification of the signature

The explainer says that 'AuthenticatorAssertionResponse.signature' will contain the signature that should be verified by the RP. WebAuthn specification has an exact signing/verifying algorithm for the signature already. In a nutshell, it is the signature over the concatenated authenticatorData and clientDataJSON. Is SPC going to overload the signing/verification algorithm to include SecurePaymentConfirmationResponse.paymentData? If so, it'd be great to understand the details.

Similar functionality for transaction confirmation in online banking applications?

I'm sorry for this issue as it seems slightly off-topic.

As I understand Secure Payment Confirmation, its use cases lay in payments with credit cards or similar?
Are you aware of similar proposed features, that leverage WebAuthn to confirm transactions inside online banking applications?

E.g. PSD2 (via RTS) of the European Union has following requirements for transaction confirmation (with dynamic linking):

RTS - Art 5 - Dynamic Linking

Where payment service providers apply strong customer authentication in accordance with Article 97(2) of Directive (EU) 2015/2366, in addition to the requirements of Article 4, they shall adopt security measures that meet each of the following requirements:
(a) the payer is made aware of the amount of the payment transaction and of the payee;
(b) the authentication code generated shall be specific to the amount of the payment transaction and the payee agreed to by the payer when initiating the transaction.
(c) the authentication code accepted by the payment service provider corresponds to the original specific amount of the payment transaction and to the payee agreed to by the payer. Any change to the amount or the payee shall result in the invalidation of the authentication code generated.
For the purpose of paragraph 1, payment service providers shall adopt security measures which ensure the confidentiality, authenticity and integrity of each of the following:
(a) the amount of the transaction and the payee through all phases of authentication.
(b) the information displayed to the payer through all phases of authentication including generation, transmission and use of the authentication code.
For the purpose of the requirement under point (b) in paragraph 1 and where payment service providers apply strong customer authentication in accordance with Article 97(2) of Directive (EU) 2015/2366 in relation to a card-based payment transaction for which the payer has given consent to the exact amount of the funds to be blocked pursuant to Article 75(1) of that Directive, the authentication code shall be specific to the amount that the payer has given consent to be blocked and agreed to by the payer when initiating the transaction.
For the purpose of the requirement under point (b) in paragraph 1 and where payment service providers apply strong customer authentication in accordance with Article 97(2) of Directive (EU) 2015/2366 in relation to payment transactions for which the payer has given consent to execute a batch of remote electronic payment transactions to one or several payees, the authentication code shall be specific to the total amount of the batch of payment transactions and to the specified payees.

As I understand it, at least payee (e.g. account number) and amount would have to be displayed to the user inside an online banking application.

Regulatory Technical Standard

Multiple versions of card art icon? (E.g. to support dark mode)

The code snippet in the explainer suggests that the caller can provide multiple icons. Wouldn't one icon be sufficient?

const publicKeyCredentialCreationOptions = {
  paymentInstrument: {
    name: 'Mastercard****4444',
    icons: [{
  	  'src': 'icon.png',
  	  'sizes': '48x48',
  	  'type': 'image/png',
    }],
  },
...

Remove fallbackUrl from explainer

The fallbackUrl parameter in the SecurePaymentConfirmationRequest dictionary was originally intended to provide an easy fallback mechanism for users of SPC, where they could pass a step-up challenge URL or similar.

This was never implemented inside Chromium, and during the Q4 2020 pilot with Stripe we didn't find any need for it either. Instead, the caller can just handle the rejected promise from request.show() and utilize their own fallback mechanism.

Unfortunately it is currently marked required so just removing it from the explainer might be confusing to folks experimenting with the implementation in Chrome today (as the API call will throw with a missing parameter). Instead, I plan to comment it as deprecated in the explainer, then land a change in Chrome to remove it from the IDL, and then finally remove it from the explainer once that reaches Stable (or once all involved parties are aware its being removed).

PROPOSAL 2: No Payment Handler Flow

As a counter-proposal to #15 here is a proposal that would require no Payment Handlers (i.e. they could potentially be deprecated entirely) but would require that instruments are stored by RPs in the browser using an ID that is both "routable" by a merchant and opaque enough that it is not sensitive to share.

This is a minor modification to the existing Secure Payment Confirmation (SPC) proposal.

Advantages:

  1. No need for Payment Handlers = very simple to implement for RPs
  2. Lower implementation and maintenance burden for browsers
  3. Much simpler Payment Request API (no need to support "payment method data" and can possibly exclude shipping details etc)
  4. Simple fallback to rendering an RP provided URL inside a modal dialogue

Disadvantages:

  1. Need a strategy to prevent instrument identifiers becoming global user identifiers
  2. No PH = no support for delegated shipping details etc

Assumptions:

  1. The RP (bank/issuer/wallet) registers payment instruments in the browser at some time when the user has authenticated themselves (e.g. login to Internet banking/wallet, complete a previous transaction)
  2. The instrument identifier is "routable" (i.e. can be used by a merchant to route an authorization request to the RP to get a challenge or fallback URL). E.g. A format-preserving tokenized card or URL
  3. The instrument identifier is opaque (does not reveal private information about the user) as it will be revealed to the merchant before SPC when the instrument is selected by the user from a browser-rendered instrument selector

Questions:

  1. Can the instrument identifier be easily rotated so it is not a global identifier shared by the browser with multiple merchants?
  2. How does an RP register payment instruments that will not be used with Secure Payment Confirmation but where the URL for the fallback flow is not same-origin as the RP? (e.g. ACS server for capturing SMS OTP is at different origin to issuer who is the RP)
  3. How will an RP manage the instruments installed in the user's browser? Will they be able to enumerate them, delete them etc?
  4. Do we need a flow that is equivalent to JIT installation of a Payment Handler?

Enrollment

RPs (issuers, wallets etc) will register payment instruments in a users browser during an enrolment flow which involves calling the WebAuthn create API to create a new PaymentCredential.

A PaymentCredential is a new type of credential which MAY be linked to a PublicKeyCredential (which may be implicitly created when registering the PaymentCredential). It contains payment instrument meta-data (i.e. a label and icon) and is mapped to one or more payment methods.

It will be possible to create a new PaymentCredential linked to an existing PublicKeyCredential. In this case the browser will invoke the authenticator's authentication flow using the details of the existing credential (as opposed to the registration flow which creates a new credential on the authenticator).

It will be possible to create a PaymentCredential that is not linked to a PublicKeyCredential. This instrument will appear in the browser-rendered instrument selector when appropriate but can't be used to invoke Secure Payment Confirmation. If a user selects one of these instruments then the merchant can only invoke the fallback authN flow by passing in an RP provided URL to render.

Whenever an RP registers an instrument there will be a user interaction whereby the user confirms the registration and their intent to use this for payments in the future. If the credential is linked to a PublicKeyCredential this will also involve a user interaction with their authenticator as with existing WebAuthn registration and authentication flows.

The installed PaymentCredentials serve multiple functions:

  1. They are used by the browser to present the user with an instrument selection list when the merchant calls PR API without providing a list of instrument identifiers. The list is filtered based on the payment methods provided by the merchant and those mapped to the credential.
  2. The label and icon are used on the Secure Payment Confirmation screen.
  3. The label and icon are rendered by the browser as part of the modal dialogue that renders the fallback URL when Secure Payment Confirmation is skipped/fails.
  4. The fallback flow is only allowed if the provided URL is same-origin with the credential RP.
[SecureContext, Exposed=Window]
interface PaymentCredential : Credential {
};

partial dictionary CredentialCreationOptions {
  PaymentCredentialCreationOptions securePayment;
};

dictionary PaymentCredentialCreationOptions {
  // |instrumentId| is a caller provided ID for the payment instrument 
  //  to which the new PaymentCredential should be bound. It should be 
  //  an opaque string generated using a payment network specific algorithm 
  //  that allows the network to identify the issuer of the instrument 
  //  and the issuer to identify the account associated with this
  //  instrument. (e.g. form-preserving card token or URL)

  required DOMString instrumentId;
  required DOMString displayName;
  required USVString icon;
  required sequence<USVString> paymentMethods;
  PaymentCredentialPublicKeyOptions createPublicKeyCredentialOptions
  PublicKeyCredentialDescriptor existingPublicKeyCredential;
};

// Either |createPublicKeyCredentialOptions| or |existingPublicKeyCredential| 
//  or both must be provided.
// If both are provided then the browser should create the credential if 
//  the existing credential doesn't exist.

dictionary PaymentCredentialPublicKeyCreationOptions {
  required PublicKeyCredentialRpEntity rp;
  required BufferSource challenge;
  required sequence<PublicKeyCredentialParameters> pubKeyCredParams;
  unsigned long timeout;
  
  // PublicKeyCredentialCreationOption attributes that are intentionally omitted:
  // user: For a PaymentCredential, |instrument| is analogous to |user|.
  // excludeCredentials: No payment use case has been proposed for this field.
  // attestation: Authenticator attestation is considered an anti-pattern 
  //  for adoption so will not be supported.
  // extensions: No payment use case has been proposed for this field.
};

Example usage:

const securePaymentConfirmationCredentialCreationOptions = {
 instrumentId: "Q1J4AwSWD4Dx6q1DTo0MB21XDAV76",
 displayName: 'Mastercardยทยทยทยท4444',
 icon: 'icon.png',
 paymentMethods: ["https://mastercard.com/pay", "https://clicktopay.com"]
 existingCredential: {
    type: "public-key",
    id: Uint8Array.from(credentialId, c => c.charCodeAt(0))
 },
 publicKeyCreationOptions: {
  challenge,
  rp,
  pubKeyCredParams,
  timeout
 }
};

// Bind new credential to |credentialId|, or create a new credential 
//  if |credentialId| doesn't exist.
const credential = await navigator.credentials.create({
  securePayment: securePaymentCredentialCreationOptions
});

Payment

When a user visits a merchant there are two possible flows before Secure Payment Confirmation (or the fallback flow) is invoked.

User Provided Instrument

  1. The merchant gets the instrument selection from the user via a form or other mechanism (e.g. selection of a card on file)
  2. The merchant sources a set of valid instrument identifiers, an optional challenge, and an optional fallback URL from the payment system.
  3. The merchant creates a Payment Request and passes the instrument identifiers into the constructor.
  4. The merchant calls canMakePayment and the browser returns a "truthy" response if one of the provided instrument identifiers identifies an installed PaymentCredential that supports one of the merchant provided payment methods. If there is an instrument linked to a PublicKeyCredential then the response also indicates that Secure Payment Confirmation is available - i.e. the response has a property canDoSecurePaymentConfirmation equal to true.
  5. The merchant calls show(). If the merchant provided multiple instrument identifiers and more than one PaymentCredential is identified by one of the supplied identifiers (this shouldn't happen unless RPs have messed up) then the browser presents the user with an instrument selection list populated with all installed PaymentCredentials that are identified by provided instrument identifiers. However, the browser will prefer to use a PaymentCredential that is linked to a PublicKeyCredential so that it can offer Secure Payment Confirmation. Therefor if only one PaymentCredential that is identified by the supplied instrument identifiers is linked to a PublicKeyCredential then that PaymentCredential is auto-selected. If more than one PaymentCredential linked to a PublicKeyCredential is identified by the provided instrument identifiers then only those are listed for selection by the user.
  6. When the user selects an instrument (or when the browser auto-selects an instrument) the instrument identifier is passed to the merchant through an instrumentSelected event emitted by the Payment Request object.

Instrument Selection Through The Browser

  1. The merchant creates a Payment Request and DOES NOT pass in instrument identifiers.
  2. The merchant calls canMakePayment and the browser returns a "truthy" response if at least one of the installed PaymentCredentials supports one of the provided payment methods. If there is an instrument linked to a PublicKeyCredential then the response also indicates that Secure Payment Confirmation is available - i.e. the response has a property canDoSecurePaymentConfirmation equal to true
  3. The merchant calls show and the browser presents the user with an instrument selection list populated with all installed PaymentCredentials that support the payment methods the merchant supports.
  4. When the user selects an instrument the instrument identifier is passed to the merchant through an instrumentSelected event emitted by the Payment Request object.
  5. The merchant uses the instrument identifier from the event to route a request to the RP to get an optional challenge and optional fallback URL for the payment (the RP may also indicate to the merchant that no further authN is required - i.e. zero-friction - in which case the merchant exits the flow)

AuthN

At this point the User Provided Instrument and Instrument Selection Through The Browser flows converge.

  1. The merchant passes the challenge and a fallback URL to the browser via a respondWith method on the instrumentSelected event.

  2. If the merchant provided a challenge and the selected instrument is mapped to a PublicKeyCredential the browser invokes Secure Payment Confirmation. The assertion generated is returned to the merchant in the PaymentResponse.

  3. If SPC fails or the merchant doesn't provide a challenge AND the merchant does provide a fallback URL then the browser shows a modal dialogue which renders the fallback URL and returns an instance of a Window to the merchant in the PaymentResponse. The fallback URL is only used if the origin is the same as the origin of the RP that enrolled the PaymentCredential. The merchant should use postMessage to communicate with the RP's window and can authenticate the user through some fallback mechanism such as SMS OTP.

Here's how a new simpler PR API could look with 3DS:

// Get instrument identifiers, challenge and fallback URL from network 
const { instruments, challenge, fallbackUrl } = get3DSResponse(pan)
const request = new PaymentRequest({
  supportedMethods: ["https://mastercard.com/pay", "http://clicktopay.com/"],
  instruments // instruments = ["412938871562965", "41290981273767562"]
},{
  currency: 'USD', value: '20.00'
})

const cmp = await request.canMakePayment()
if(cmp) {
  request.addEventListener("instrumentSelected", e => {
	e.respondWith({
      challenge,
      fallbackUrl
    })
  }
  const {securePaymentConfirmation, fallbackWindow} = await request.show();

  if(securePaymentConfirmation) {
	do3DSStuff(securePaymentConfirmation)
    return
  }

  if(fallbackWindow) {
    fallbackWindow.addEventListener("message", e => {
      //Handle messages from issuer window
    })
  }
} else {
  //Legacy 3DS flow
}

Here's how a new simpler PR API could look WITH instrument selection:

const request = new PaymentRequest({
  supportedMethods: ["https://mastercard.com/pay", "http://clicktopay.com/", "https://google.com/pay"],
},{
  currency: 'USD', value: '20.00'
})

const cmp = await request.canMakePayment()
if(cmp) {
  request.addEventListener("instrumentSelected", e => {
   
    if(e.supportedMethods.includes("https://google.com/pay")) {
        // Skip SPC and show Google Pay modal
		e.respondWith({
	      fallbackUrl: "https://google.com/pay?instrument=" + e.instrumentId
	    })
        return
    }

    const { challenge, fallbackUrl } = get3DSResponse(e.instrument)
    e.respondWith({
      challenge,
	  fallbackUrl
	})
  }
  const {securePaymentConfirmation, fallbackWindow} = await request.show();

  if(securePaymentConfirmation) {
	do3DSStuff(securePaymentConfirmation)
    return
  }

  if(fallbackWindow) {
    fallbackWindow.addEventListener("message", e => {
      if(e.origin == "https://google.com/")) {
        //Message from Google Pay window  
      } else {
        //Message from 3DS fallback window 
      }
    })
  }
} else {
  //Legacy checkout flow
}

FIDO Credential ID vs Payment Instrument ID

My understating of the explainer is that the FIDO Credential ID is used to query the credentials and trigger the SPC flow for the matching credential.

It has been discussed during the annual (virtual) F2F meeting that the new Payment Instrument ID could be introduced instead of the generic FIDO Credential ID. When a new payment instrument gets enrolled in the user agent the Payment Instrument ID would be generated. The ID would be associated with the card meta-data, FIDO Cred ID, and RP ID stored by the user agent. During checkout, the client would provide only Payment Instrument ID(s) in the SPC request and the user agent would find the matching stored credentials based on the FIDO Cred Id and RP ID associated with the Payment Instrument ID.

How to handle stale displayName and icon?

@adrianhopebailie raised this in https://github.com/rsolomakhin/secure-payment-confirmation/issues/10#issuecomment-666970228:

I worry about the browser-side mapping of instruments to credentials and the high likelihood that the data gets stale.

The simplest approach is for the issuer to update an existing credential with a new label and icon when the user visits the issuer's website. But I wonder if a user cannot be guaranteed to revisit. Perhaps some kind of push mechanism for the RP to update the instrument label and icon would be helpful.

Authentication versus Authorization

For the coming Task Force to consider.

The core difference between authentication and authorization is that authentication occurs between two end points, while the result of an authorization may be intended for consumption by a party which is not necessarily even known at time the authorization is created.

Another limitation with authentication is that it more or less presumes that data is in clear and that the authenticating party is "trusted". Merchants are usually not considered as trusted (in computer security terms). That Merchants authenticate card holders is actually a strange thing in itself, this is a task for Issuers.

State-of-the art payment systems like Google Pay encrypt authorization data.

Authorization-based schemes are thus inherently more flexible with respect to backend infrastructure design, but do not combine well with authentication-based schemes like 3DS.

If the authorization path is taken, the most logical foundation would be CTAP2 rather than WebAuthn.

Note: "pure" authorization schemes like EMV do not depend on externally provided "challenge" data, they rely on locally generated nonce objects and time stamped data making "replay" protection / detection straightforward. Replay may even be permitted if services are idempotent, for dealing with network glitches and similar temporary outages.

From the FIDO Web Pay specification:

Through the use of a dedicated credential database, associated FIDO keys can be freely used by the FWP implementation, while remaining invisible and protected from access by all parties but their respective Issuer.

Supporting roaming authenticators

When we create a new payment credential using your roaming credential, it's implied that the browser stores the credential displayName and icon so that when it's presented as an authentication option in the future, the browser can provide the user that useful bit of context that "this will use your Blue Authenticator to approve putting this purchase on your Yellow Card ending in 9999."

Moving the Blue Authenticator to another computer though and doing the same operation with the same account will prvoide a compatible credentialId that the browser can then use to approve this new purchase ... but there's no knowledge of what that credentialId would be approving for. E.g., the context would be, "This will use your Blue Authenticator to approve for an unknown payment type."

Browsers could sync that data around, but many people have many reasons to not sync, so this is a "normal" edge case. What should happen when a browser can't display useful context? Ignore that credential ID?

Clarify security properties of the cryptogram

The SPC spec should provide advice/a threat model on how to securely handle the cryptogram.

Questions:

  • What are the requirements on the nonce (random, secret, etc.)? See #26.
  • How can the cryptogram be safely verified by multiple parties (merchant, card network, issuer)?
  • What data elements need to be verified in order to prevent phishing? (Is it required to verify the merchant origin, and who should do that?)
  • How do we support situations where the issuer/relying party may not be invoked before the payment, e.g. Touch ID autofill?

https://lists.w3.org/Archives/Public/public-webauthn-pay/2020Sep/0009.html

Rich merchant details displayed in the payment confirmation dialog

Currently, in the pilot implementation, only the domain name of the merchant website is displayed in the payment confirmation dialog. I'd like to propose to enhance the visual representation of the merchant by displaying also the title and favicon of the page from which SPC request has been triggered. Of course, it's the subject of the availability of the data.

Using PaymentCredential for vanilla WebAuthn authentication.

The explainer says that PaymentCredential is new type of credential used with Credential Management API. The credential is PublicKeyCredential with special features. Can the same credential be used for SPC flow and authentication with vanilla WebAuthn?

The use-case I have in mind is this:

  1. End-user registers a `PaymentCredetnial' to the RP e.g. issuer.com. The credentials include the payment instrument meta-data.
  2. Merchant triggers authentication with SPC as described in the explainer.
  3. The same credential can be used by the RP outside of the SPC flow to authenticate the end-user and get the regular WebAuthn assertion.

Can you please confirm SPC allows such a use-case?

Support for A2A payments

Note: this is a question for the coming spec, not the Stripe pilot.

I have not found any information on how SPC is supposed to deal with Account-to-Account payments like SEPA Instant.

A common characteristic of these systems is that they usually do not come with a physical card (and associated printed account number), making it somewhat unclear how they fit a 3DS world. Existing A2A payment systems do not require users to memorize or explicitly type account numbers.

SPC should not constrain how WebAuthn nonce is created

Based on discussions with various people, I understand that there may be different ways to create the nonce that is used as input to Web Authentication, including:

  • Fetching information from a server (e.g., the relying party)
  • Browser generation of a nonce using random information (e.g., the transaction id of PR API).

In short, I have heard that the system should not rely on any single way of creating the nonce.

(That does not mean that every approach will be equally trusted.)

Can a merchant ensure that SPC will be used before invoking PR API?

It would be ideal if a merchant could construct a PR object and use the output of canMakePayment to determine if SPC is possible.

const cmp = await pr.canMakePayment()
if(cmp.canDoSecurePaymentConfirmation) {
  //Yay! Frictionless, secure, payments FTW!
  const result = pr.show()
} else {
  //Boo! [fall back to traditional flow]

This would be for the case when the merchant is depending on the browser to provide an instrument selector and then a PH would be invoking SPC

Allow the original RP of a PaymentCredential to update the payment instrument details

The instrument data (i.e. card art, instrument descriptor) associated with a PaymentCredential may become stale over time. It would be useful for the original relying party to be able to update the instrument data.

@tblachowicz: Would you mind adding a bit more details on how you envision this fit into a user flow? Do you want this capability when user visits their bank (the RP)? Are you also thinking of push update without the user visiting the RP's website?

Change payment amount from SPC call within a payment app?

I spoke with Frank Hoffmann today who asked whether it would be possible for a payment app that calls SPC (assuming it can) to change the total.

The use case is:

  • User agrees with merchant to pay $100
  • When user chooses payment method, the payment method supports installments (e.g., $25 every week)
  • The SPC transaction window should say "Do you agree to pay $25?"
  • Subsequent payments are handled by card-on-file

Ian

PROPOSAL: Alternative Secure Payment Confirmation Flow

What follows is an alternative flow and API design for SPC that enables a zero-friction flow where the payment network supports this.

Thanks to Gerhard for the idea of using the PReq in this way.

Advantages:

  1. Support for zero-friction flow if RP decides that full WebAuthn flow is not needed
  2. No fingerprinting by RP without explicit RP UI shown to user
  3. Strong privacy model (No data returned to merchant until payment is completed by user)
  4. Can be used with existing 3DS 2.0 backend messages and flows
  5. Secure Payment Confirmation is not invoked by any origin except the RP
  6. No need for browser to maintain instrument to credential mapping
  7. Simpler DX with clear separation of concerns between payment instruments (used to identify a payment account) and credentials (used to identify a user)

Flow without instrument selection

e.g 3DS 2 with legacy card entry form

  1. User provides details of payment instrument (e.g. card details)
  2. Merchant contacts RP to get a URL for the RP payment method manifest
  3. Merchant calls Payment Request using RP URL as payment method
  4. Browser checks for Payment Handler that supports RP payment method and installs JIT if necessary
  5. Browser invokes Payment Handler and passes it details of payment instrument provided by merchant.
  6. Payment Handler does risk assessment on the transaction and if necessary (i.e. zero-friction not possible) gets a list of credential IDs and a challenge to do SPC. (Note: PH is executed in a 1st party context and has access to cookies and local storage in the RP domain. i.e. Good chance that zero-friction is possible despite no fingerprinting)
  7. If zero-friction is possible return response to merchant and merchant completes the payment via the network.
  8. If SPC is required AND there are credential IDs to use the Payment Handler invokes SPC providing the browser with the list of credential IDs and the challenge.
  9. The resulting assertion is returned to the merchant
  10. If the SPC fails the PH calls e.openWindow to render the fallback step-up authentication UI (e.g. SMS-based OTP or similar)

Flow with instrument selection

e.g. 3DS 2 with browser-rendered instrument selection or Google Pay

  1. User clicks pay button and merchant calls Payment Request using a supported network URL(s) as the payment method(s)
  2. Browser checks for instruments installed via Payment Handlers that support provided network payment method(s) and prompt user to select one.
  3. Browser invokes Payment Handler of chosen instrument and passes it details of payment instrument.
  4. Payment Handler does risk assessment on the transaction and if necessary (i.e. zero-friction not possible) gets a list of credential IDs and a challenge to do SPC. (Note: PH is executed in a 1st party context and has access to cookies and local storage in the RP domain. i.e. Good chance that zero-friction is possible despite no fingerprinting)
  5. If zero-friction is possible return response to merchant and merchant completes the payment via the network.
  6. If SPC is required AND there are credential IDs to use the Payment Handler invokes SPC providing the browser with the list of credential IDs and the challenge.
  7. The resulting assertion is returned to the merchant
  8. If the SPC fails the PH calls e.openWindow to render the fallback step-up authentication UI (e.g. SMS-based OTP or similar)

Assumptions:

  • Each instrument added by an RP payment handler will support multiple payment methods. In the most common case this will include a payment method identifier that uses the origin of the RP and a payment method identifier of the network.
  • The Payment Method Identifier of the RP is used to invoke the RP Payment Handler directly when the user has already provided payment instrument details and the RP is known by the merchant.
  • The Payment Method Identifier of the network is used to invoke any RP Payment Handler that supports that method and has already installed an instrument in the browser (i.e. prompting the user to select the instrument and thereby invoking the Payment Handler)

Example using existing 3DS 2 back-end flows

  1. Alice enters the PAN of her Bank of America VISA card into a merchant website
  2. Using the BIN of her PAN the merchant performs a PReq and gets back the following 3DS Method URL https://bankofamerica.com/web-payments/visa-platinum

NOTE: In a standard 3DS 2 flow the merchant is expected to render an iframe using this URL and the ACS uses this to fingerprint the user's browser. The data collected by the ACS is associated with a threeDSServerTransID generated by the merchant.

  1. The merchant calls Payment Request API using the 3DS Method URL as the payment method identifier and passing Alice's PAN and the 3DS Server Transaction ID it generated in the request.
const request = new PaymentRequest(
  [{
    supportedMethods: 'https://bankofamerica.com/web-payments/visa-platinum',
    data: { 
      cardholderAccountNumber: '512312346523765', 
      threeDSServerTransID: '12345678-1234-5678-abcd-eFABCDEF0123' 
    }
  }],
  {
    total: {
      label: 'total', 
      amount: {currency: 'USD', value: '20.00'}
    }
  });
  1. If the issuers Payment Handler is already installed then it is invoked via the PaymentRequestEvent otherwise the JIT install steps are followed first:
HEAD /web-payments/visa-platinum HTTP/2
Host: bankofamerica.com

And the server would then respond:

HTTP/2 204
Link: </pay/payment-manifest.json>; rel="payment-method-manifest"
{
  "default_applications": ["https://bankofamerica.com/web-payments/webappmanifest.json"],
  "supported_origins": ["https://bankofamerica.com"]
}
  • The browser will install the Payment Handler that is defined by the app manifest at https://bankofamerica.com/web-payments/webappmanifest.json

  • If the JIT install fails the PR API will return an error and the merchant falls back to legacy 3DS

  1. If the payment handler was previously installed or the browser has visited this origin before the PH it will have access to cookies, local storage and WebCrypto APIs to perform some zero-friction checks such as verifying that this is the same device used previously. In Alice's case, she has visited the BofA website in this browser and completed a previous legacy 3DS checkout so she has cookies from bankofamerica.com that are read by the PH. The PH goes online to ACS to get a risk score for the transaction passing the transaction details, PAN and 3DS Server Transaction ID. The request will carry all of the previously installed cookies.

NOTE: The PH is not able to do fingerprinting without calling e.openWindow and showing the user some UI.

NOTE: Other means of doing client-side user identification are possible given the context. e.g. The PH could use local storage or the WebCrypto APIs to securely identify the user without the need for WebAuthn at this stage.

  const response = await fetch("https://bankofamerica.com/3ds/2/risk-check", {
    method: 'POST',
    cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
    credentials: 'same-origin',
    headers: {
      'Content-Type': 'application/json'
    },
    redirect: 'follow',
    body: JSON.stringify({
      threeDSServerTransID: '12345678-1234-5678-abcd-eFABCDEF0123' 
      cardholderAccountNumber: '512312346523765', 
      amount: {currency: 'USD', value: '20.00'}
    })
  })
  const {result, spc} = await response.json()
  1. Alice has no instruments installed in her browser (since the PH was JIT installed) so the PH installs the selected instrument before invoking SPC:
if(result.instrument) {
  await e.instruments.set(
    result.instrument.key, // "98745678-1234-5678-abcd-er76rqwffd86a"
    result.instrument.value);
/* result.instrument.value =
    {
      name: "Visa ****3765",
      icons: [{
        src: "/pay/visa.png",
        sizes: "32x32",
        type: "image/png",
      }],
      methods: [
        "https://visa.com/web-payments/click-to-pay",
        "https://bankofamerica.com/web-payments/visa-platinum"
      ]
    }
  );
*/
}
  1. Since the purchase is of a high-value the ACS requests that SPC be used if available and returns a list of credentials that it knows have been enrolled by Alice on her various devices. The PH invokes SPC.
  if(acsResponse.result === "SKIP-AUTHN"){
    e.respondWith(acsResponse)
    return
  }

  if(acsResponse.result === "DO-SPC"){
    const {challenge, allowCredentials} = spc

    // Internally the browser turns this into a WebAuthn get assertion call
    const assertion = await e.securePaymentConfirmation({
      instrumentId: result.instrument.key,
      challenge,
      allowCredentials,
      60000
    })
    
    if(assertion){
      e.respondWith(assertion)
      return
    }
  }
  1. If SPC is not possible (e.g. no credentials returned or available) the PH invokes a legacy authN flow
  e.openWindow('https://bankofamerica.com/sms-otp/)
  ....

Does the browser receive credential IDs or instrument IDs?

During checkout, the browser needs to know the WebAuthn credential IDs associated with the instrument to generate an assertion. The issuer can return the credential IDs directly or return the instrument IDs, which the browser will dereference into credential IDs using an internal mapping. The internal mapping is updated when enrolling a new credential.

For the pilot, both options will work equally well.
Post pilot, having the instrument ID abstraction may be useful. For example, it can be used as a new routable ID on the network for the combined instrument selection & authentication flow.

The instrument ID format will be defined by each payment method. So maybe it can also be a composite data structure that contains a credential ID and any other metadata the issuer wants to include.

Clarify cardinality between PaymentCredential and payment instruments

Arguments for 1 credential for many instruments:

  • The bank really only wants to authenticate the person. Having 1 credential that works across multiple instruments and possibly even the bank account login is more convenient for the user, as they only need to enroll once.

Arguments for 1 credential for 1 instrument:

  • Sharing a credential mixes security domains. This is especially true when sharing between login and payment.

Next step is to try to enumerate attack vectors for sharing credential.

Add profile identifier to payment credential structure to support credential fetching?

Hi all,

In the SRC flow, a persistent user identifier is used to fetch card metadata for display and selection by the user. As browser behavior changes around 3p cookies, implementations are likely suffer.

I was chatting with @adrianhopebailie today about how we might address this (e.g., in a credential management API sort of way). We convered on a particular user experience that we liked and thought we could achieve this by building on top of the (still-being-designed) SPC payment credential data. Imagine for a moment that a payment credential can optionally include an identifier that means "This payment credential is part of a user profile that the RP identifies with this identifier."

We are very conscious of tracking, so this idea endeavors to only provide information with user consent.

Here's how it might work (all from a 3p context)

  1. The user clicks a button in a 3p context, which calls Payment Request with payment method identifier "PMI"
  2. In the API, the 3p requests that the browser prompt the user to select an identity for from the list
    of payment credentials associated with "PMI"
  3. Results:
    0: silently return null
    otherwise: the browser prompts the user to choose an identity. The browser returns (only) the identifier
    associated with the payment credential. (For future discussion: optimizations)

Thus, the identifier is shared with the 3p after two user gestures:

  1. Click a "buy" button
  2. Select an identity to make a payment.

The identifier can be used to fetch more payment instruments associated with that user identity, and those can be displayed to the user for selection, followed by SPC authentication.

Thus we have parallel behaviors:

  1. For identity: ask the browser to have the user pick an identity from stored payment credentials, otherwise silently return null.

  2. For authentication: ask the browser to authenticate the user for a list of payment credential identifiers, otherwise silently return null.

Integrating SPC with Open Banking

Discussion for the coming SPC specification.

Integrating SPC with Open Banking is a complex matter. The most intricate part of the puzzle is where exactly a PISP fits into such a schema. Dirk Balfanz's presentation highlights the problem:
https://www.w3.org/2020/02/3p-creds-20200219.pdf#page=5
In this slide the User is supposed to authorize a payment to his/her PISP. This introduces several obstacles:

  • The PISP concept (unlike AISP) does not presume that the User is known by the PISP making "Your PISP" a less useful term
  • The interest by Merchants and Banks adding a new User-facing service is low

Chris Wood's recent F2F presentation shows the consequences:
https://docs.google.com/document/d/1qjBPa6l0EM9A3sLl9neccq_8UPHe90jXTGXqcbge2vQ


Note that this example concentrates on Confidential Clients, but it could equally apply to Public Clients with the right tweaks.

The initial consent will incorporate the SPC Credential ID as an additional property, named SPCCredentialId:_

{
  "Data": {
    "ReadRefundAccount": "Yes",
    "Initiation": {
      "InstructionIdentification": "ACME412",
      "EndToEndIdentification": "FRESCO.21302.GFX.20",
      "InstructedAmount": {
        "Amount": "99.99",
        "Currency": "GBP"
      },
      "CreditorAccount": {
        "SchemeName": "UK.OBIE.SortCodeAccountNumber",
        "Identification": "08080021325698",
        "Name": "ACME Inc"
      },
      "RemittanceInformation": {
        "Reference": "FRESCO-101",
        "Unstructured": "Internal ops code 5120101"
      }
    },
    "SCASupportData": {
      "SPCCredentialId": "8bbea266-921b-4015-9bc9-a5017b310b54"
    }
  },
  "Risk": {
    "PaymentContextCode": "EcommerceServices",
    "MerchantCategoryCode": "5967",
    "MerchantCustomerIdentification": "053598653254"
  }
}

On success the bank will return an identifier for the newly created Consent entity in the property ConsentId:

{
  "Data": {
    "ConsentId": "f73ff601-e969-43d1-961e-fdfcbd1b170d",
    "Status": "AwaitingAuthorisation",
    "CreationDateTime": "2017-06-05T15:15:13+00:00",
    "StatusUpdateDateTime": "2017-06-05T15:15:13+00:00",
    "ReadRefundAccount": "Yes",
    "Initiation": {
      "InstructionIdentification": "ACME412",
      "EndToEndIdentification": "FRESCO.21302.GFX.20",
      "InstructedAmount": {
        "Amount": "99.99",
        "Currency": "GBP"
      },
      "CreditorAccount": {
        "SchemeName": "UK.OBIE.SortCodeAccountNumber",
        "Identification": "08080021325698",
        "Name": "ACME Inc"
      },
      "RemittanceInformation": {
        "Reference": "FRESCO-101",
        "Unstructured": "Internal ops code 5120101"
      }
    },
    "SCASupportData": {
      "SPCCredentialId": "8bbea266-921b-4015-9bc9-a5017b310b54"
    }
  },
  "Risk": {
    "PaymentContextCode": "EcommerceServices",
    "MerchantCategoryCode": "5967",
    "MerchantCustomerIdentification": "053598653254"
  },
  "Links": {
    "Self": "https://api.alphabank.com/open-banking/v3.1/pisp/domestic-payment-consents/58923"
  },
  "Meta": {}
}

The Relying Party will use this value to populate the challenge property of the PaymentRequest call. The following snippet uses the existing example from the SPC proposal, amended to include the challenge property:

const securePaymentConfirmationRequest = {
  action: 'authenticate',
  challenge: 'f73ff601-e969-43d1-961e-fdfcbd1b170d',
  credentialIds: [Uint8Array.from(atob('8bbea266-921b-4015-9bc9-a5017b310b54'), c => c.charCodeAt(0))],
  networkData,
  timeout,
  fallbackUrl: "https://fallback.example/url"
};

const request = new PaymentRequest([{
    supportedMethods: 'secure-payment-confirmation',
    data: securePaymentConfirmationRequest
  }],
  {
    total: {
      label: 'total', 
      amount: {
        currency: 'GBP', 
        value: '99.99'
      }
    }
  });
const response = await request.show();
await response.complete('success');

Once the request is made and an Authentication Assertion successfully elicited by the Payment Handler it is sent to the bank using an authentication flow supported under FAPI


ALTERNATIVE

By putting the PISP in the same position as a payment gateway, none of the peculiarities of Open Banking payments need to trickle down to the User layer (and SPC), giving a simpler solution and as well as a better UX. The impact on Open Banking APIs would be marginal; the big job is the unavoidable Access Server/FIDO which in all variants becomes a special purpose system with its own API.

@danyao

The instrument ID should not be easily usable by the merchant to track the user

This issue replaces #22.

Issue 22 was one solution to the problem: the instrument ID should not be usable to track the user. Requiring the instrument ID to not leave the browser may overconstrain us.

Here is one proposal: When the relying party registers the payment credential with the browser, they register some significant number of instrument IDs (e.g., 1024), all of which map to the actual instrument on the RP's back end. When the user selects a payment credential, the browser returns a random instrument ID to the merchant. That would likely make tracking more difficult. It would not likely require a lot of storage in the browser (since users won't have a large number of cards). It would be easy for the browser computationally, and not involve any network connections during the transaction.

I had also thought about hashing the instrument ID with the transaction ID to introduce dynamic data, but that would likely create more computation burden for the relying party.

Ian

Requirements and Good Practices around Unenrollment

Hi all,

Lawrence Cheng and I were chatting today and he raised an issue I had not yet thought about: unenrollment of SPC credentials. It seems to me there are multiple topics here:

  • The user's lifecycle management of stored SPC credentials (add/delete)
  • Server-initiated requests to delete stored SPC credentials
  • Server-side management of associations between SPC credentials and payment instruments. Suppose I lose my laptop and I want to tell my financial services provider: please forget all (or some?) of my SPC credentials.

Are the second two necessary? If so, from an API perspective is anything needed? Or is this just "good practice" documentation?

I have not yet looked into what FIDO says about unenrollment. That could be a good starting point.

Ian

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.