Skip to content

Instantly share code, notes, and snippets.

@adrianhopebailie
Last active April 15, 2020 21:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adrianhopebailie/74f3b41f935fb60895e97977da1bfb7a to your computer and use it in GitHub Desktop.
Save adrianhopebailie/74f3b41f935fb60895e97977da1bfb7a to your computer and use it in GitHub Desktop.
WebAuthn + Web Payments = Transaction Confirmation

WebAuthN + Payment Request = Payment AuthZ

Can we use a combination of Payment Request API and WebAuthN API to get Transaction Confirmation (Dynamic Linking)?

Transaction Confirmation (TxConf) is a feature of FIDO that guarantees to the Relying Party (RP) that the user saw the same transaction details that are signed by their authenticator, i.e. WYSIWYS (What You See Is What You Sign)

Why is transaction confirmation important?

In the absence of TxConf an authenticator can ONLY assert that a challenge (generated by the RP to prevent replays) was signed inside the authenticator at the consent of the user (who provided the neccessary gesture to "unlock" the authenticator, e.g. biometric scan, PIN etc).

The authenticator CAN NOT guarantee anything about what the user was prompted when they signed the challenge.

This is fine if simply authenticating the user is the requirement (e.g. for login). However, when requesting a user consent to, and authorize, a transaction this is only half of the problem solved.

For example, imagine a bank user is being requested by a third-party to authorize a payment from their bank account. The UI that displays the transaction detail and the data passed to the authenticator to sign is entirely controlled by the third-party (except the challenge which was provided by the bank). There is no guarantee that the data displayed and the data signed are the same.

The third-party MAY prompt the user to authorize a payment of $10 but submit a transaction to the bank of $10 000 along with a valid signature from the user's authenticator.

Background

This is roughly the current state of things:

  • When WebAuthn is invoked the user interface is controlled by the platform so it is not as secure as a secure hardware display but it's definitely better than the application/Web display under control of the RP that invokes WebAuthN.
  • Very few authenticators support Transaction Confirmation as they don't have a secure display.
  • Browsers have not implemented the txAuthSimple or txAuthGeneric extensions (which are the WebAuthn entrypoint to this functionality) for this reason and therefore these are likely to be removed in future.
  • Browsers have also expressed concerns about accepting free-text as input to a TxConf algorithm.
  • PaymentRequest objects have structured transaction details (not free text) which could form the basis of the Transaction Confirmation Display.

Proposal

We need a way to invoke WebAuthn specifically for payments such that we can leverage:

  • The fact that the transaction data that is held by the PaymentRequest object is well structured
  • The browser/platform rendered UI that is shown to the user when getting an attestation

Instead of calling WebAuthn via navigator.credentials.get(...) we want to invoke the WebAuthN internals automatically at some point in the Payment Request API flow, pass the details of the payment into this process and get back an attestation that these details were displayed to the user when they were prompted to authenticate.

To do this, we need to know who the RP is so we can invoke the authenticator with the correct details. That is, we need to know what the RP origin is, the credential id that should be used to sign the challenge and what challenge to issue the authenticator.

The RP origin is the origin of the payment handler that is being invoked to handle the Payment Request so we assume that during regoistration that payment handler provided the credential ids that are valid to use.

When the user selects a Payment Handler that has registered for this capability/feature, the browser initiates the algorithm that would usually be invoked via navigator.credentials.get() using a combination of parameters that were pre-registered by the payment handler (credential id etc) and parameters derived from the Payment Request itself.

The user is shown a prompt to authenticate but the browser UI also shows the details of the requested payment (amount, currency and origin of the beneficiary).

There is no need for the payment handler to show any UI as it has a signed attestation that it can return to the merchant in response to the Payment Request.

The merchant can now submit the attestation as proof that the user (authenticated by the authenticator) also consented to the specific details of the tx (as displayed by teh browser and encoded in the Payment Request). The merchant will then pass this attestation to the RP system via the payment rails to initiate the payment.

Questions

  1. Can the challenge passed to the authenticator also be generated by the browser, possibly including the unique Payment Request ID (a random UUIDv4)?
  2. Is there a way to "attest" that the user saw the Payment Request details when being prompted to authenticate and therefore the RP can trust that the details of the transaction have been confirmed and not just the authentication of the user?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment