w3c / webauthn

Web Authentication: An API for accessing Public Key Credentials
https://w3c.github.io/webauthn/
Other
1.17k stars 169 forks source link

FIDO Payment Support #1570

Closed cyberphone closed 3 years ago

cyberphone commented 3 years ago

Since the SPC specification is to be discussed at https://github.com/w3c/webpayments/wiki/Agenda-FTF2021, I took the liberty outlining an enhanced scheme that may serve as "inspiration". It is not entirely complete (enrollment is currently missing), but the core is hopefully understandable. The proposal mainly deals with security constructs and data flows.

Updated: 2021-02-19

Enhancements

Although not a part of this specification, the underpinning authorization scheme also opens the door to non-direct payments, including secure (tokenized) versions of Card-on-File.

Prerequisite - Payment Credentials

The scheme outlined here depends on that the User already has received a payment credential from the Issuer in an enrollment process. A payment credential is supposed to at least contain the following elements:

A payment credential is associated with a specific paymentMethod established during enrollment.

Detailed Operation

The different steps in following state diagram are described in this section. state-diagram Note: this specification does not elaborate on the return data from the Issuer etc.

1. The Merchant creates payment request data (PREQ) and invokes the payment request API with it:

{
  "id": "7040566321",
  "payee": "Rocket Shop",
  "amount": {
    "currency": "EUR",
    "value": "435.00"
  }
}

Note: the JSON object above outlines the conceptual data before being translated into a compliant Payment Request call. It seems that payee currently have no obvious place in the API.

2. The Browser responds with PREQ rendered in a user interpretable fashion: browser-display Non-normative UI.

3. The User authorizes the request with a fingerprint, PIN, or similar.

4. After successful user authorization, the Browser MUST perform the following internal steps.

4.1 Calculate a Base64Url-encoded SHA256 hash of PREQ, canonicalized according to RFC8785. Expressed as a formula: BASE64URL(SHA256(RFC8785(PREQ))). Applied to the sample data, the result of this operation should be "Zf6qUOoA3NWM77rksuji2tE7tlGHrzu9K5Y_AGn5tkw".

4.2 Create an authorization data object (AD) with data needed for processing by the Issuer:

{
  "requestHash": {
    "algorithm": "S256",
    "value": "Zf6qUOoA3NWM77rksuji2tE7tlGHrzu9K5Y_AGn5tkw"
  },
  "payeeHost": "spaceshop.com",
  "accountId": "FR7630002111110020050014382",
  "timeStamp": "2021-02-18T10:32:35+01:00"
}

4.3 Using the FIDO signature key, sign AD using JWS/CT resulting in the following completed AD object:

{
  "requestHash": {
    "algorithm": "S256",
    "value": "Zf6qUOoA3NWM77rksuji2tE7tlGHrzu9K5Y_AGn5tkw"
  },
  "payeeHost": "spaceshop.com",
  "accountId": "FR7630002111110020050014382",
  "timeStamp": "2021-02-18T10:32:35+01:00",
  "signature": "eyJhbGciOiJFUzI1NiIsImp3ayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2IiwieCI6IjZCS3hwdHk4Y0ktZXhEekNraC1nb1U2ZFhxM01iY1kwY2QxTGFBeGlOclUiLCJ5IjoibUNiY3ZVem00NGozTHQyYjVCUHlRbG9ROTF0ZjJEMlYtZ3plVXhXYVVkZyJ9fQ..XvwOEMX4CG8l5nq-rOSkEbdFRcrhtAdQ6s1HFtLgiWMoNliiPSJnurmBnkBzudoLucBLVRwql6ZWANq1AALcXA"
}

Although not visible in the listing above (due to JWS' Base64Url-encoding requirements on JWS header data), AD signatures MUST provide a key identifier. In the sample, the following JWK holding the public key was used:

{
  "kty": "EC",
  "crv": "P-256",
  "x": "6BKxpty8cI-exDzCkh-goU6dXq3MbcY0cd1LaAxiNrU",
  "y": "mCbcvUzm44j3Lt2b5BPyQloQ91tf2D2V-gzeUxWaUdg"
}

4.4 For privacy and security reasons, the completed AD object MUST be encrypted by a public key provided by the Issuer through the payment credential. This specification builds on JWE (RFC7516) using the compact serialization mode. The selection between an RSA or ECDH encryption scheme is at the discretion of the Issuer. AD objects MUST be JSON-serialized to UTF-8 before being encrypted. The resulting JWE string would look something like this (with line breaks for display purposes only):

eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.OKOawDo13gRp2oja
HV7LFpZcgV7T6DVZKTyKOMTYUmKoTCVJRgckCL9kiMT03JGeipsEdY3mx_etLbb
WSrFr05kLzcSr4qKAq7YN7e9jwQRb23nfa6c9d-StnImGyFDbSv04uVuxIp5Zms
1gNxKKK2Da14B8S4rzVRltdYwam_lDp5XnZAYpQdb76FdIKLaVmqgfwX7XWRxv2
322i-vDxRfqNzo_tETKzpVLzfiwQyeyPGLBIO56YJ7eObdv0je8860ppamavo35
UgoRdbYaBcoh9QcfylQr66oc6vFWXRcZ_ZT2LawVCWTIy3brGPi6UklfCpIMfIj
f7iGdXKHzg.48V1_ALb6US04U3b.5eym8TW_c8SuK0ltJ3rpYIzOeDQz7TALvtu
6UG9oMo4vpzs9tX_EFShS8iB7j6jiSdiwkIr3ajwQzaBtQD_A.XFBoMYUZodetZ
dvTiFvSkQ

To simplify documentation, the JWE string is subsequently referred to as "JWE-Encrypted-AD".

Note that due to the end-2-end encryption scheme, the domain constraints usually associated with FIDO, do not apply.

4.5 Put the encrypted AD into a payment response object (PRES) together with clear text data needed for payment "backend" processing:

{
  "encryptedAuthorization": "JWE-Encrypted-AD",
  "paymentMethod": "https://europeanpaymentsinitiative.eu/spc",
  "issuerId": "https://mybank.fr/payment"
}

paymentMethod is the actual SPC method used. See https://github.com/w3c/webauthn/issues/1570#issuecomment-780611040.

Note that by encrypting authorization data, the "routing" of payment requests with respect to the Issuer is separated from account numbers. By using URLs like in the example, the need for databases holding BIN numbers is eliminated.

5. The Browser returns PRES to the Merchant.

6. The Merchant puts its original PREQ and the received PRES into an authorization request object (AREQ):

{
  "paymentRequest": {
    "id": "7040566321",
    "payee": "Rocket Shop",
    "amount": "435.00",
    "currency": "EUR"
  },
  "encryptedAuthorization": "JWE-Encrypted-AD",
  "paymentMethod": "https://europeanpaymentsinitiative.eu/spc",
  "issuerId": "https://mybank.fr/payment"
}

7. The Merchant sends AREQ to the Acquirer service associated with the specific paymentMethod. Note that authentication of AREQ is out of scope for this specification.

8. The Acquirer validates the authenticity and syntax of the received AREQ as well as looking up the Issuer through the supplied issuerId.

9. The Acquirer augments the received AREQ with additional data (like Merchant collection account), and forwards the completed object to the designated Issuer. Note that authentication of AREQ is out of scope for this specification.

10. The Issuer MUST now perform a number of steps to verify the correctness of the received AREQ. With respect to the User the following steps are the most significant:

10.1 Decrypt the encryptedAuthorization object in AREQ using the Issuer specific (but shared) decryption key. Set result as AD.

10.2 Retrieve the signature key declared in the JWS header of the AD signature element. Abort if unknown.

10.3 Verify that the retrieved signature key is associated with the AD accountId element. Abort on failure.

10.4 Validate the AD signature using the retrieved signature key. Abort on failure.

10.5 Perform the same calculation as specified in 4.1 on the received paymentRequest object and compare the result with the AD requestHash. Abort on failure.

10.6 Check that the AD timeStamp element is within limits. Tentative: CurrentTime - 600s < timeStamp < CurrentTime + 60s. Abort on failure.

10.7 To cope with possible replays, check that the received AD has not already been utilized. Ideally, the Issuer should support idempotent operation to facilitate benign transaction retries.

Available funds also needs to be validated but that is out of scope for this specification. @equalsJeffH @nadalin @rlin1

adrianhopebailie commented 3 years ago

How does the browser determine which payment credential to use in step 2? My assumption is that the user has multiple and they are only usable on specific payment networks for specific payment method.s

cyberphone commented 3 years ago

Right, this proposal does not describe the selection mechanism because the assumption is that the existing PaymentRequest selection scheme will be sufficient.

cyberphone commented 3 years ago

Although security for the "backend" is not covered here, there are a few apparent things worth mentioning.

cyberphone commented 3 years ago

PaymentRequest

const methodData = [{
  supportedMethods: 'https://emvco.com/spc/visa'
},{
  supportedMethods: 'https://emvco.com/spc/mastercard'
},{  
  supportedMethods: 'https://europeanpaymentsinitiative.eu/spc'
}];

const request = new PaymentRequest(methodData,{
  id: '7040566321',   // Mandatory for SPC
  total: {label: null, amount: {currency: 'EUR', value: '435.00'}},
  payee: 'Space Shop'   // Possible API enhancement
});

const response = await request.show();
await response.complete('success');

A payment method intended for use with the SPC payment handler, would then establish this link during payment credential enrollment. This would enable merchants to either use individual "pay buttons" for each payment method, or support collections of useful methods to their liking.

SPC must obviously include a selection UI itself. Swiping credentials icons could be an option. Updated the UI accordingly...

There may be a need for payment system specific data during invocation or in payment credentials. The inclusion of such data would need to be standardized to keep SPC fully universal.

Notes:

equalsJeffH commented 3 years ago

ISTM that this issue ought to more properly be filed at https://github.com/rsolomakhin/secure-payment-confirmation

cyberphone commented 3 years ago

@equalsJeffH it may seem like that but the fact is that mine[1] and Google's[2] takes on SPC only have the name in common.

As a thought experiment you could try to envision what users (UI-wise) would have to put up with and banks would have to build (giant central registries holding enrolled account numbers) in order to apply 3DS/step-up authentication concepts to IBAN accounts like the sample's FR7630002111110020050014382.

/Anders

1] Effectively a "technology refresh" of EMV adapted for the Web. EMV remains the to date only payment authorization scheme that enjoys both real and de-facto standards status. The https://www.w3.org/TR/payment-request/#canmakepayment-method should fully replace the need for user-hostile and privacy-impeding 3DS "step-up" methods required by the current W3C/Google proposal. @christiaanbrand @srsheth

2] Builds on leveraging two technologies that were designed for other purposes. FIDO: User authentication rather than payment authorization. 3DS: Supporting users who do NOT have access to sophisticated client-side crypto and trusted browser code which was a great idea back in 1998 when it was created. @balfanz @ve7jtb @dturnerx

rsolomakhin commented 3 years ago

@cyberphone, if I understand the gist of your proposal, there appears to be two primary differences from SPC:

  1. The challenge comes from the merchant instead of the bank.
  2. The browser stores some extra data for each payment credential, so it can return user's account number, encrypted with the public key of the bank, too.

Is that a fair summary?

I think perhaps this proposal would be more clear if the enrollment step was described or specified. How would it work?

cyberphone commented 3 years ago

Hi @rsolomakhin, I believe the differences are much bigger.

  1. 3DS/SPC is an additional (and optional) card-holder authentication step introduced before the actual payment transaction: https://stripe.com/docs/payments/3d-secure. It is possible that Stripe's implementation does something else but the current SPC state-diagrams are pretty hard to follow so I'm not able to tell πŸ€” I have not the faintest idea how SPC could deal with SEPA and similar A2A (account to account) payments.

  2. EMV is a unified and optimized single-step, "store-and-forward" payment request requiring no prior third-party interaction with issuers or handing out account numbers by users. In my take on EMV, (FIDO Web Pay), the browser would together with FIDO tokens form a universal wallet. https://github.com/rsolomakhin/secure-payment-confirmation/issues/33. Encrypted authorizations (not account numbers), is the only thing that conceptually differs from EMV but it is also the core of the idea making the system universal with respect to payment systems. That is, enabling "routing" of requests with respect to issuers to be independent of account numbers (e.g. https://mybank.fr/payment)

The differences on the browser side should be rather moderate since both concepts build on FIDO tokens and a secure browser-resident payment UI/handler. Enrollment is yet to be described but AFAICT the major difference is in the payment handler database since SPC defines a single payment method while FIDO Web Pay makes the FIDO tokens dynamically define the actual payment methods (they are just URLs), all implicitly linked to the built-in payment handler. @dturnerx

cyberphone commented 3 years ago

@rsolomakhin Major issues with both solutions is that:

FIDO Web Pay (in contrast to SPC), should be attractive for Open Banking TPPs who could finally get away from systems requiring users to select bank in order to make a purchase. Note though that Open Banking is a rather slow boat...

Personally I believe the code that is currently intended to be a part of the browser, should long-term rather be a part of the client platform because then the same scheme and "virtual cards" could be used everywhere. Such a change would be invisible to all actors.

Conclusion: there is no "low-hanging fruit" or quick wins here. However, the availability of:

should be of interest for all but suppliers of proprietary payment systems.

rsolomakhin commented 3 years ago

@cyberphone - What do you mean by a built-in universal payment handler? I wonder whether that make the browser into yet another payment app that websites have to support, a la https://xkcd.com/927/.

cyberphone commented 3 years ago

What do you mean by a built-in universal payment handler? I wonder whether that make the browser into yet another payment app that websites have to support

@rsolomakhin It is possible that I got this entirely wrong πŸ™ƒ but my interpretation of the SPC explainer is that:

My idea is simply making the built-in code more universal based on the assumption that user authorization of card payments and for example SEPA credit transfers do not motivate separate handlers since they (AFAICT...) only differ on account data and named method.

Although Saturn is just a PoC, I consider the concept above fully verified. The Saturn wallet does not know anything about specific payment systems and it still works with quite different backend flows. BTW, this is a yet another reason to why I couldn't use PaymentRequest for Android as intended: it only supports statically declared methods πŸ˜’ Updating manifests or apps is not an option if you want a neutral (=universal) Wallet.

Since SPC does not rely on manifests I think this proves another point of mine: the manifest system adds considerable hassles but little or no value for native mode payment handlers. TEE attestations during enrollment performs this role while OS/apps version data supplied by payment handler authorization messages cover SW updates as well.


Before rushing things you should consider that this may very well be the only shot FIDO get at payments. If there is a desire making this great technology relevant for banks, payment support is a MUST. Apparently no banks are directly involved in these discussions (they usually require NDAs), so you rather have to guess what could be needed. Enabling credit transfers is though a known feature since it is already fully established in the Netherlands and in Scandinavia. It also the target for the multi-billion Euro project known as the European Payments Initiative (https://www.epicompany.eu/). These systems are without exceptions based on mobile apps. However, they have a rather limited range geographically speaking as well as being entirely proprietary. Here lies an opportunity for FIDO/Google/W3C making a difference. @balfanz

@adrianhopebailie

cyberphone commented 3 years ago

If my interpretation of 3DS/SPC is correct, the following should give you an indication of the huge differences in complexity between EMV/FIDO and 3DS/SPC: 3ds

The security models are also quite different: in 3DS it is the Merchant who is the RP, while in EMV it is the Issuer which seems more logical. Unless there is some kind of communication between the ACS and the "PAY" processor, it is not clear how the Issuer can know if the User actually have been properly pre-authenticated.

@rsolomakhin @equalsJeffH

cyberphone commented 3 years ago

@equalsJeffH @ianbjacobs @dturnerx @rsolomakhin @nadalin @balfanz I would rather claim that whatever FIDO solution the Web Payment WG takes on it will be perceived as the "official standpoint" for the (entire of) W3C, FIDO alliance, EMVCo, and Google, which IMO motivates an extended discussion. BTW, I have now cleaned-up the "spec" above (it has numerous of flaws): https://fido-web-pay.github.io/ It might be worth knowing that it does things not even Google and Apple Pay can do 😁 As expressed on LinkedIn in a somewhat market-ish way: FWP


This specification has though a serious drawback: it would (if getting traction) put W3C in a difficult position requiring constant updates in order to remain competitive with the App world. This requires extending the scope to PoS and P2P. This is actually no problem at all, you just move the FWP implementation down into the platform layer which also has huge advantages for users and browser vendors since there would only be a single (system-wide) FWP "Wallet".

SPC would not require anything like that since it is virtually impossible to extend.

rsolomakhin commented 3 years ago

@cyberphone wrote:

I would rather claim that whatever FIDO solution the Web Payment WG takes on it will be perceived as the "official standpoint" for the (entire of) ...

At this stage, perhaps it would be more accurate to state that the organizations are exploring the benefits of FIDO through discussions and experimentation.

cyberphone commented 3 years ago

Yes @rsolomakhin, the mentioned organizations may have had discussions but the results of these have not been made public.

You probably do not agree, but I consider the combination of

as W3C's last (and certainly the best) chance moving the payment industry forward. That is, the stakes are sky-high!

Although I'm just a WPWG mailing-list subscriber, I get the impression (by reading the minutes) that everything else is pretty much on hold making SPC a likely "default".

equalsJeffH commented 3 years ago

On 2021-03-17 call: The WG consensus is that these payments-oriented discussions are not relevant to the webauthn WG and belong elsewhere, e.g., https://github.com/w3c/payment-request/issues and/or https://github.com/rsolomakhin/secure-payment-confirmation/issues

cyberphone commented 3 years ago

@equalsJeffH @emlun @nadalin The raised issues are not related to the PaymentRequest API since nothing new is requested. Filing an issue on the Secure Payment Confirmation (SPC) project that effectively suggests dropping the idea altogether would be pretty strange. This is clearly a charter question involving not only the W3C, but the FIDO alliance, the Chromium team, and EMVCo as well.

Unlike SPC, Google pay is (with respect to the user) an end-2-end secured solution and it even encrypts authorizations.

I wish you and the W3C luck with the project "Making 3D Secure great again" 🀣

Leaving the topics here /Anders

cyberphone commented 2 years ago

The requirements imposed by SPC makes SPC an integral part of a revised WebAuthn charter, otherwise SPC would simply put not work. Some of the proposals aired, even affect FIDO/CTAP.

Before you add SPC to the WebAuthn charter, I would suggest taking a peek at https://github.com/mozilla/standards-positions/issues/570#issuecomment-972578433 which summarizes the somewhat voluminous data above, into a short table, which also includes a comparison with Apple Pay. @YubicoDemo @nadalin @ve7jtb @selfissued

To date unresolved SPC issues include: