w3c / webauthn

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

Cross origin authentication without iframes (accommodating SPC in WebAuthn) #1667

Open akshayku opened 2 years ago

akshayku commented 2 years ago

On WebAuthn WG call on 2021-08-25, a proposal concerning secure payment confirmation (SPC) was discussed which probably originated from web payments groups. Attaching for more details: [WebAuthn WG August 2021] Secure Payment Confirmation.pdf

In above proposal, a mini proposal is to open up authentication to cross origin without iframes. Opening up this issue to hopefully have the concentrated conversation around cross origin authentication without iframes and want to talk about security, privacy and user experience and potential misuse.

So at the moment, we don't allow authentication outside of origin in webauthn. We allowed it in iframes in L2, but don't allow it for any other website to be able to invoke .get() call credentials without iframes.

Recently, we discussed to open up .create() call inside iframes. Till this point RP is in control. If it chooses to, like all of non-payment scenarios, it can choose to not enable these calls in iframes. And if they do, they know who the parent is so that they can potentially filter out origins that they trust.

I see three kind of RPs with different levels of control.

  1. RP who never wants to do .create() or .get() calls outside of their origin. Current webauthn spec protections allow that which really helps in phishing resistant property of WebAuthn.
    • Most RPs live in this space
  2. RP who is OK with iframes but only want to do in iframes because they are still in control of who can invoke webauthn ceremonies.
  3. RP who wants .create() and .get() calls outside of origin. Like merchants, who wants to do on-behalf of banks.
    • The above Web Payments proposal is not proposing .create() call outside of iframes at the moment. But I heard @christiaanbrand saying that he wants to do that in future.

The most concern I have is around the third category of RPs/Scenarios which will negatively impact Category 1 and also category 2.

IIUC, the proposal is to only allow credentials who are marked as SCP compliant to be opened up for now for authentication in cross origin case.

If we cannot determine this without tampering, then we have privacy issues. A phishing website will get the credentialID and invoke it in their origin, user will be prompted with the dialog, which most likely they don't much read, and user approves and website knows that user has credential for a website which they have no right to enquire.

In above context, let's get one thing out of the way. CredentialIDs are public and that's why we don't store PII information in that. In webauthn designs, we allow with username flows, where given a username, credentialIDs being returned for passwordless authentication silently. Ofcourse, RP can add fake one, but they need to also provide the real ones. Even outside webauthn, credentialIDs are kind of treated as semi public info. And till now this was not an issue because no other origin can really use them. So credentialIDs will be known to many parties.

Another point I heard was around it is only applicable for non-discoverable credentials. I don't understand why. I can understand that this design only works if used in allowlist context, which can be satisfied by both non-discoverable as well discoverable credentials. And restricing it to only with allowlist, I am not sure what we are getting. As mentioned above, credential IDs are not really protected in any full secure way by the RPs.

Third argument I heard that any websites ability to popup authentication, even if we restrict it SCP credentials only is only a nuisance. I argue that it is a privacy issue and a possibly a phishing vector. It gives ability for a random RP to almost know for certainty that a credential exist for a website. And that is why, the second category above which says, I have cases around cross-origin authentication, but I only want it to be inside an iframe. And that should be RP's choice. Even if this is nuisance, it seriously hampers the webauthn brand.

Till now, I am only thinking from RP's persctive. I haven't thought through, where the user choice in all of this.

Overall, it seems that this is dangerous and in pursuit of solving one desire to not have iframes (which I don't disagree with per say, but just recently we rejected other legitimate use cases around raw signatures), we are messing up with core fundamentals too much here. Ofcourse, I don't have the full design and I may be wrong here.

@agl @christiaanbrand @equalsJeffH @ve7jtb for above questions and clarifications if I misunderstood things.

cyberphone commented 2 years ago

SPC builds on a model that requires untrusted third-parties (merchants) dealing with credentialId and card data in clear. State-of-the-art systems like Apple Pay need none of that. In practice the SPC API requires outsourcing to trusted service providers to be invoked which is an unusual feature for Web APIs.

https://github.com/cyberphone/doc/blob/gh-pages/payments/review-secure-payment-confirmation.md#technical-issues

akshayku commented 2 years ago

@cyberphone , Although your comments are related, I want this issue to be focused on implications of opening up the webauthn API in cross-origin without iframe context to existing RPs who have nothing to do with payment scenarios. I would prefer not discussing merits of SPC with other models on this issue.

For example, if I am an RP who does not care about payments at all, how do I prevent any random website from starting a webauthn operation on my behalf.

It is more than just a nuisance for such RP. It is also about webauthn brand. Today an RP can say that no other website can invoke such an operation. And I would like that property to remain if we allow such proposal. If that conversation changes to we don't know who can invoke us and RP has no control, that is a problem. Even if server rejects such a response, it hurts the webauthn brand IMO.

cyberphone commented 2 years ago

@akshayku If I understood this correctly, the idea is that this feature would indeed only apply to keys that were explicitly created for SPC, "payment keys".

akshayku commented 2 years ago

Probably, but I don't understand how browser will determine that. If that results in authenticator deciding it, then that webauthn system pop still comes up probably resulting in "No such credentials found". Which no other origin has ability to do today. And that is a UI problem.

cyberphone commented 2 years ago

@akshayku The process is approximately like this:

The "black box" concept used by Apple Pay et al, would if applied to FIDO not require a single change in the WebAuthn access model.

cyberphone commented 2 years ago

This is how the Web Payment folks describe the process above: https://lists.w3.org/Archives/Public/public-webauthn/2021Aug/att-0129/_WebAuthn_WG_August_2021__Secure_Payment_Confirmation.pdf#page=13 In the real world the credential discovery process is much more complex and practically always require outsourcing to scale.

christiaanbrand commented 2 years ago

I'll let Stephen respond to Akshay's question. But, before that, two notes/questions:

  1. Today, WebAuthn can be used (at least for Get operations) in iFrames. And, as far as I know, up until this point, we were fine with it. There's nothing an RP can do to prevent (and I also don't think they need to be able to do that). It has no impact on either security or privacy from my perspective. Any disagreements on that?

  2. Anders, though you're correct in saying that untrusted merchants will get to deal with credentialIds, I don't think that's a problem for the security of our implementation. Like public keys, they're not supposed to be secret, although there is an argument here about linkability (privacy), since we're already dealing with card numbers I think that's okay? In other words, SPC's security model does not depend on the integrity of untrusted merchants.

akshayku commented 2 years ago

Today, WebAuthn can be used (at least for Get operations) in iFrames. And, as far as I know, up until this point, we were fine with it. There's nothing an RP can do to prevent (and I also don't think they need to be able to do that). It has no impact on either security or privacy from my perspective. Any disagreements on that?

No disagreements on this, but I think we can improve it to be more granular between allowing it to be iFrames vs no iFrames which browser can do for every RP, instead of RP having to do it. With this third class of RPs who are OK with SPC, I have some design in mind, but want to confirm first the above questions.

Usability is something I am concerned about and I want current property of no-one else being able to ask for my credentials to remain.

That property of only allowing RPs to decide what they want is something I want to explore technically.

stephenmcgruer commented 2 years ago

Hi Akshay,

You're asking an important question here, so thank you and I apologize for not covering this explicitly in my presentation. We definitely have to make sure that RPs opt-in here and that that is supported at the technical level.

which probably originated from web payments groups

For the record, there is no probably. Secure Payment Confirmation has been developed entirely within the W3C Web Payments Working Group from its inception >1 year ago to today.

[...] I don't understand how browser will determine [whether a credential is SPC-enabled].

The unappealing answer for today is: we currently store a browser-local list of credentials created in that browser with SPC permission, and require at auth-time that a credential matches the list. This has many issues of course, and so is not the long-term plan.

The longer-term plan should be authenticator-based, I think - perhaps a platform authenticator API in the intermediate future, or a CTAP bit in the longer-term to enable all authenticators. Or there may be a superior solution that the WebAuthn WG are better able to come up with (as my FIDO-level knowledge falls short!).

If that results in authenticator deciding it, then that webauthn system pop still comes up probably resulting in "No such credentials found". Which no other origin has ability to do today. And that is a UI problem.

My hope is that the same APIs required for Conditional UI will enable SPC without a platform 'No such credentials' prompt. The question one is trying to answer from the browser code is "Do any of these credentials exist on this device and are enabled for SPC". The first half is close to Conditional UI, the second half is new.

This long term plan would require Discoverable Credentials, and that is why I believe SPC should require them too.

sbweeden commented 2 years ago

I don't quite understand why there should be an exception (alternative approach) for SPC credentials. I'm happy to hear the argument for this, but from a purist POV, what really makes them special that they deserve to be treated differently from credentials used for other authentication scenarios?

I would hope that whatever model is arrived at it would be suitable and relevant for all WebAuthn credentials and as much as possible all use cases, and that such an exception doesn't just exist to placate those opposed to changing the current model.

cyberphone commented 2 years ago

@sbweeden The biggest change required by SPC is liberating keys domain wise: https://w3c.github.io/secure-payment-confirmation/#sctn-payment-extension-registration That is, a payer must be able to exercise his/her payments keys with any merchant.

There are two other alternatives which do not require any updates of WebAuthn:

akshayku commented 2 years ago

The unappealing answer for today is: we currently store a browser-local list of credentials created in that browser with SPC permission, and require at auth-time that a credential matches the list. This has many issues of course, and so is not the long-term plan.

This is not a good design. This does not work cross-browser.

The longer-term plan should be authenticator-based, I think - perhaps a platform authenticator API in the intermediate future, or a CTAP bit in the longer-term to enable all authenticators. Or there may be a superior solution that the WebAuthn WG are better able to come up with (as my FIDO-level knowledge falls short!).

Probably. But not sure we need anything else than what we already have. If we are having a clause of only SPC credentials work here, then we are leaving behind lot of external authenticators currently in the market. Which probably we don't need to. I would like to understand whether we have a need for separating out normal credentials vs SPC credentials. And if there is a need, can that be satisfied with having two subdomains like login.RP.com and payments.RP.com?

My hope is that the same APIs required for Conditional UI will enable SPC without a platform 'No such credentials' prompt. The question one is trying to answer from the browser code is "Do any of these credentials exist on this device and are enabled for SPC". The first half is close to Conditional UI, the second half is new.

@sbweeden has a point. Why only restrict to SPC type of credentials? Why not everything?

The other thing here is "on this device" clause. We believe that user should be able to use external authenticators if they choose to. And we don't want SPC to be restricted only to platform authenticators. And for external authenticators, there cannot exist an API which says tell me the credentials when that device is not even plugged in at that moment. Hence the UI prompt occurs to guide the user first and that is a big problem in all of this.

In your current design, RP is not in control. Credential IDs are public and anyone who has Credential IDs can ask for authentication if we allow cross-origin authentication. Big problem is that pop up which removes the behavior currently which says that only RP control authentication request ceremony and no one else can even start the operation. Even if browser adds this information and RP can check on the server in the response, it is big problem for the WebAuthn brand and we don't want anyone else to ask for WebAuthn authentication on our behalf. That would be one of my requirement that RP must be in control of whether anyone else can ask for WebAuthn operation to even start the browser WebAuthn operation. RP must be be able to decide what behavior they want and what scenarios they want to support.

The solution I am thinking of is along the following lines.

This long term plan would require Discoverable Credentials, and that is why I believe SPC should require them too.

I wonder whether you choose non-discoverable because that what Android supports today or there is some other reason? For comparison, Windows only support discoverable credentials and not planning to support non-discoverable credentials. And I would like to Windows Hello and external authenticators to also be able to satisfy the SPC requirements because user verification is what should matter to the RPs. Whether those credentials are in allow list or not, should not matter IMO.

cyberphone commented 2 years ago

@akshayku @sbweeden There may be a terminology issue buried here.

"Cross-origin" for authentication usually means that you have something that can be used for authentication to multiple and potentially independent RPs like an X.509 certificate.

"Cross-origin" for SPC however, is not about multiple RPs, but to permit arbitrary domains launching authorization/authentication requests to the RP that once created the key in question.

These use cases do not appear to have much in common.

emlun commented 2 years ago
  • RP declares the security/usability/scenarios supported for WebAuthn credentials at their origin

    • May be RP has a .well-known URL/file which browser will check if accessed from another origin that is not the top level origin. I think we did something similar for U2F in terms of appid?

    • Two permissions. RP can specify multiple permissions.

    • Allow WebAuthn in iframes

    • Allow WebAuthn in cross-origin

  • Browser checks for above permissions when WebAuthn is not done in RP's origin.

I've been thinking about something along these lines too. This could also enable a lot more, here are some ideas:

The .well-known resource could specify an allow-list of which domains may use WebAuthn cross-origin. Although I've understood that payment providers may want to allow any merchant, so maybe a dynamic solution similar to the Access-Control-Allow-Origin header would be preferred.

If the .well-known resource is dynamic, it could also return a list of allowed credential IDs for the operation. That could remove the need for an SPC bit stored on the authenticator, preserving backwards compatibility with existing authenticators.

Taking that one step further, the .well-known resource could return all the request parameters, taking even more complexity off the merchant. The merchant might not even need to see the user's credential IDs at all (though the response would still be returned to the merchant, so the merchant would see that credID and user handle unless we obfuscate that too somehow).

As a rough but concrete example incorporating all of the above, say the flow could go something like this:

  1. Merchant somehow asks user for some user ID and for which bank it is. Maybe a credit card number, or a user ID and domain stored in a browser wallet, etc.
  2. Merchant calls bank.com/.well-known/webauthn/spc-begin with body {"user_id": "<user ID>", "tx_info": { <requested transaction amount, recipient, currency, etc> }
    • Note that we assume nothing about tx_info here - its format could be unique per bank, so this could probably be generalized to non-payment applications too.
  3. Bank initiates SPC ceremony and returns opaque token z3/kmIC9+6z2ZoO7T7IvngMwa1BfQXVLcxAYsFOeUI8= referencing this ceremony state
  4. Merchant calls navigator.credentials.get({ spc: { rpId: "bank.com", token: "z3/kmIC9+6z2ZoO7T7IvngMwa1BfQXVLcxAYsFOeUI8=" } })
  5. Browser calls bank.com/.well-known/webauthn/spc-get with header X-SPC-Request-Id: z3/kmIC9+6z2ZoO7T7IvngMwa1BfQXVLcxAYsFOeUI8=
  6. Bank returns a PublicKeyCredentialRequestOptions structure (would need us to define encoding for byte arrays)
  7. Browser proceeds as if this PublicKeyCredentialRequestOptions had been passed as publicKey in a normal navigator.credentials.get() call
  8. Merchant receives PublicKeyCredential result, sends this back to bank somehow, bank confirms transaction somehow

I'm sure there are lots of problems and incompatibilities here, as I know very little of how payment systems work. One clear drawback is that this would require a whole protocol on its own for the browser<->bank communications, with all the inertia that entails. But has something along these lines been considered?

ve7jtb commented 2 years ago

Dirk and I talked about something like what @emlun is proposing a couple of years ago for permission based cross-origin authentication requests.

One issue was the merchants didn't want the browsers making a call to the bank for each request for performance reasons.

One thing we considered was the RP publishing a JWKS at a .well-known. That would contain a public key that the bank would use to sign delegation authorizations.

The merchant would send the card number to the bank and get back a list of RPID and a time-limited dedication authorization that would go to the browser allowing the RP to treat the RP as a proxy for the specified RPID.

The browser would need to cache the public key but that could be relatively long lived and used across multiple merchants.

The browser would check that the deligation ticket in the request is valid before allowing the RP to specify a third party RPID.

If we wanted to not keep a cross domain flag in the authenticator for the credential then we could probably do that if the allow list was part of the signed object. That would prevent the merchant from making a request with credentials in an allow list that the RP doesn't intend for cross domain.

I think it would solve Akshays problem with only allowing specific proxies.

I don't quite get why the requirement for discoverable credentials. While this should work for discoverable credentials when an allow list is provided, I don't see any reason that a discoverable credential is required.

If we decide to store a flag for the credential that could be stored in the credentialID allowing non discoverable credentials to work as well.

So I mostly agree with @emlun but think the browser should just be getting a key in the .well-known so it can be cached and be replicated via CDN.

cyberphone commented 2 years ago

@emlun wrote:

I'm sure there are lots of problems and incompatibilities here, as I know very little of how payment systems work. One clear drawback is that this would require a whole protocol on its own for the browser<->bank communications, with all the inertia that entails. But has something along these lines been considered?

The only thing that has been considered is adopting the Google/Stripe pilot as the foundation for a thing that now are just days from becoming a public draft. SPC is effectively W3C's last chance in a very long time creating a useful Web based addition to the payment landscape. My analysis (FWIW) indicates that SPC will not prevail: https://github.com/cyberphone/doc/blob/gh-pages/payments/review-secure-payment-confirmation.md#external-review-googlew3c-secure-payment-confirmation-spc

That SPC does not (unlike just about every other payment method in existence), present itself as a branded icon in checkout pages reveals a limited understanding of commercial and marketing realities. The conveners are probably counting on that Stripe and their likes will market SPC but they won't. SPC is just a feature in a long list of methods supported by proprietary "checkout APIs".

IMO any alternative work should start by asking the question: What problems do the existing on-line payments methods suffer from and is there something we could do about this? If that question only returns increased security and/or marginally better UX, there is nothing to do because that's not enough to move this very slow market. Put in other words: a useful solution must also function as an "enabler" for new functionality that should be attractive for consumers, merchants, and banks. Since none of these parties are active in public standardization efforts this comes with certain challenges 😎

@stephenmcgruer @christiaanbrand

cyberphone commented 2 years ago

@emlun Wrote:

  1. Merchant somehow asks user for some user ID and for which bank it is. Maybe a credit card number, or a user ID and domain stored in a browser wallet, etc.

This is where the troubles begin. Merchants asking for something related to the user versus having that in a browser wallet is a watershed issue because the latter does in a proper design (e.g. Apple Pay), eliminate the need sharing PII like user Ids or card numbers with untrusted third parties (e.g. merchants).

stephenmcgruer commented 2 years ago

Apologies for the delay here folks, I got wrapped up with other happenings this week. Starting with Akshay's latest comment:

This is not a good design. This does not work cross-browser.

We are in agreement! It's a hack, to speak plainly, which suffices to let us see if the general concept of SPC (trustable user authentication initiated by merchants) is attractive to the payments industry.

I would like to understand whether we have a need for separating out normal credentials vs SPC credentials. [...] @sbweeden has a point. Why only restrict to SPC type of credentials? Why not everything?

One thing to make clear, from my perspective - the term 'SPC credential' exists only to differentiate the ability to utilize the credential in a third-party initiated authentication. I do not expect a long-term solution in WebAuthn to even refer to SPC - the concept might be called 'third-party enabled credentials' or something like that (I'm bad at naming!). SPC then becomes a spec that relies on such 'third-party enabled credentials'.

We believe that user should be able to use external authenticators if they choose to. And we don't want SPC to be restricted only to platform authenticators. And for external authenticators, there cannot exist an API which says tell me the credentials when that device is not even plugged in at that moment. Hence the UI prompt occurs to guide the user first and that is a big problem in all of this.

I think this might still be compatible with SPC. To maintain authentication ceremony privacy, SPC has to show a user dialogue whether or not the passed credentials match the device. In the match case, it's a transaction dialog (followed by WebAuthn if the user agrees to verify the transaction). In the non-match case, it's a form of error dialogue that we try to make payment-specific. It seems like the latter could additionally allow for the user to plug an external authenticator in at that moment, and it would 'retry' the matching logic?

In your current design, RP is not in control. [...]. RP must be be able to decide what behavior they want and what scenarios they want to support.

As discussed in the call; I (and I think at least @christiaanbrand will agree with me) am asserting that the RP does have control, in that this behavior is opt-in when they create the credential. I agree they don't have absolute control, but as per below I don't think that's desirable for the payments case.

The solution I am thinking of is along the following lines. [...]

The issue with this solution, as with @emlun 's, is what @ve7jtb points out below - it puts the bank back in the middle of the payment transaction. This re-introduces the performance and reliability issues we were trying to get away from (though I will cede that it does still keep the user-confusion issue out of it as the user never sees this).

Moreso, this solution, as with @emlun 's and @ve7jtb 's do not integrate with or build on top of existing widely-used payment protocols that banks are familiar with and which they trust. SPC's current model should (I believe) work with any payment protocol where the merchant and the bank talk on some form of backend protocol - which is most of them.

I wonder whether you choose non-discoverable because that what Android supports today or there is some other reason? For comparison, Windows only support discoverable credentials and not planning to support non-discoverable credentials. And I would like to Windows Hello and external authenticators to also be able to satisfy the SPC requirements because user verification is what should matter to the RPs. Whether those credentials are in allow list or not, should not matter IMO.

I think you perhaps misread: we choose Discoverable, not non-Discoverable. That's actually why SPC cannot launch currently on Android, because I think that Discoverable Credentials are required for it's long-term success. (I could be wrong!).

(Although perhaps we are just using different definitions here... you're correct that currently SPC requires the merchant to pass in the list of credentials, which is very 'non-Discoverable' like. The reason was that in our opinion from the website's perspective credentials should only be Discoverable for the RP, not for a third-party.)

stephenmcgruer commented 2 years ago

I don't quite get why the requirement for discoverable credentials. While this should work for discoverable credentials when an allow list is provided, I don't see any reason that a discoverable credential is required.

The reason I've pushed for Discoverable Credentials isn't related to the third-party initiated authentication ceremony. It is related to SPC's ability to only show the browser transaction UX if the credentials match this device (i.e. if there's a chance the user could succeed, assuming they wish to and that they can pass the WebAuthn ceremony). This seems very close to Conditional UI (which is in some ways solving the same question... roughly), and Conditional UI requires Discoverable Credentials.

If we can find a way of doing that without requiring Discoverable Credentials, SGTM!

cyberphone commented 2 years ago

@stephenmcgruer wrote:

SPC's current model should (I believe) work with any payment protocol where the merchant and the bank talk on some form of backend protocol - which is most of them.

This is not entirely correct, in most cases there is a third party in the middle.

For EMV which is the most widely used payment authorization system there is no direct communication between the merchant and the customer's bank; it is a pure store-and-forward system depending on trusted intermediaries for the communication with banks (which BTW often is bank specific).

3DS (and SPC) introduces a new requirement: retrieving the URL to the bank's (ACS) Access Control Server using the card number as key. According to the 3DS specification this operation requires certified merchant software and an X.509 certificate for authentication which is why 3DS more or less presume outsourced operation. That is, merchants will in general not be able invoking SPC themselves.

How does this relate to this issue you may [rightfully] wonder? Well, by rather building on EMV you get away from just about all privacy, UI, credential discovery, scalability, logotype integrity, and certification issues mentioned here and in the SPC draft. An EMV variant would preferably not be built on top of the WebAuthn API, it would rather use CTAP2 and funnel hashed transaction requests through clientDataHash (and thus eliminating clientDataJSON). Backing authenticators would still be 100% compatible with WebAuthn in case RPs would like to use them for login as well.

cyberphone commented 2 years ago

I'm happy that the wallet concept completely does away with this issue as well as issues like:

adrianhopebailie commented 2 years ago

@cyberphone what you are proposing is not impossible as an eventual end-goal: a Web Payments API that involves payment specific interactions with secure hardware (as opposed to going via generic WebAuthn).

However, as I think you know, the scope of such an undertaking is HUGE.

The goal of SPC, as @stephenmcgruer alludes to above, is to figure out if the market is even interested in merchant initiated payment authN. Hence, the current design has some hacks but it will get us on a road to more experiments and iterations and ultimately a solution that the market will actually use.

SPC is not a payment method, your comments about branding and icons suggest you are either missing the point or refuse to listen (I've pointed this out to you before). SPC is an authN mechanism that can be used by ANY payment method. To leverage SPC a payment method must define a way for the merchant to discover the credential IDs it can use for a particular transaction. In a card transaction using 3DS, this is defined in the 3DS spec, other payment methods will define other ways for this to work. That's not in scope for SPC.

Please stay on topic in this thread so we can focus on the issue of cross-origin auth.

adrianhopebailie commented 2 years ago

@stephenmcgruer - maybe I am being stupid but I can't think of a use case that is impossible if SPC simply required merchants to embed an RP iframe.

I presume the issue with this is not the technical limitations?

stephenmcgruer commented 2 years ago

@stephenmcgruer - maybe I am being stupid but I can't think of a use case that is impossible if SPC simply required merchants to embed an RP iframe.

I presume the issue with this is not the technical limitations?

Looking only at 3DS*, I would generally agree with that statement.

As per the presentation I gave in the WebAuthn WG two weeks ago, the main reasons are reducing friction, avoiding merchants having to embed resources from arbitrary banks, and the aforementioned reliability of issuer web-services. Stripe had a great writeup on this a long time ago, and I would welcome input from @jcemer if they wish to add more explanations, reasons, and/or data :).

cyberphone commented 2 years ago

@adrianhopebailie https://github.com/w3ctag/design-reviews/issues/544#issuecomment-915822393

ianbjacobs commented 2 years ago

I deleted @cyberphone's comment. This is not part of our agenda and was never more than a comment and therefore there is no need for noise about it on this thread.

emlun commented 2 years ago

I've discussed a bit with @ve7jtb and we have a proposal for how the "SPC bit" could be stored for external authenticators: essentially, we could "namespace" the RP ID.

Specifically: when a merchant initiates SPC registration for RP ID acmebank.com, the browser calls authenticatorMakeCredential and sets the RP ID to spc://acmebank.com and clientDataJSON.action: "payment.create". Similarly, for SPC authentication the browser calls authenticatorGetAssertion with RP ID spc://acmebank.com and clientdataJson.action: "payment.get". The precise format and naming of the namespace/prefix is of course up for discussion (maybe payment:// to mirror action?), but that's the idea. Platform authenticators can store the "SPC bit" however they like without affecting the API.

Some implications of this approach (not always obvious if they are advantages or disadvantages):

  1. Backwards compatible all the way back to U2F security keys
  2. Works with resident credentials on existing FIDO2 security keys
  3. The RP remains in control of which credentials have the SPC capability
  4. Credentials must be created with the SPC capability explicitly enabled; it is impossible for existing credentials to be opted in accidentally
  5. SPC credentials will be exclusively for SPC and cannot also be used for login

Although, (3), (4) and (5) don't have to be true for platform authenticators - those certainly could manage both the "SPC bit" and SPC access dynamically if they so wish.

This wouldn't solve the issue of allowing access to the SPC API in the first place (preventing rogue UI prompts), though.

Thoughts on that?

timcappalli commented 2 years ago

I like this pattern. It would also allow for future use of WebAuthn credentials for ephemeral session binding across devices (cross-device wallet use cases).

equalsJeffH commented 2 years ago

update 19-Nov-2021: Ignore this post -- I'd (obviously) forgotten about OpenSSH's existing use of the ssh: namespace in RP IDs as akshayku and ve7jtb point out below.


WRT @emlun and @ve7jtb's above proposal, while I'm sympathetic with the goal of finding a clean way to denote webauthn/fido creds as being "enabled"/"authorized" for use in payments contexts, the primary issue I see with this particular approach is that the RP ID is defined as a valid domain string, not a URL (or serialized origin). Setting them to the latter may be problematic.

emlun commented 2 years ago

the primary issue I see with this particular approach is that the RP ID is defined as a valid domain string, not a URL (or serialized origin). Setting them to the latter may be problematic.

I agree, and the proposal doesn't change that in the web-layer API. From the perspective of the RP, the RP still sets the RP ID to acmebank.com, for example. Only in the under-the-hood CTAP call does the browser add the namespace prefix so that the authenticator instead sees scp://acmebank.com.

...ah, right, but that means that the RP will need to verify the response rpIdHash against SHA256(prefix + rpId) instead of the usual SHA256(rpId). That doesn't seem to me like a big issue, since the RP already needs special logic to process an SPC response anyway. But it does mean that platform authenticators must necessarily work in the same way - which might also be a good thing, if the list above is considered advantages.

equalsJeffH commented 2 years ago

update 19-Nov-2021: Ignore this post -- I'd (obviously) forgotten about OpenSSH's existing use of the ssh: namespace in RP IDs as akshayku and ve7jtb point out below.


... the proposal doesn't change that in the web-layer API.

Agreed. the RP just needs to explicitly set the RP ID rather than let the client platform set it ambiently.

... that means that the RP will need to verify the response rpIdHash against SHA256(prefix + rpId) instead of the usual SHA256(rpId). That doesn't seem to me like a big issue, since the RP already needs special logic to process an SPC response anyway. But it does mean that platform authenticators must necessarily work in the same way ...

Agreed. AFAICT authenticators only do comparisons on RP ID strings and the hashing you note.

Though, authnrs with displays may show RP IDs to users eg during authn ceremonies, and there's also the "credential management" (list creds, etc.) displaying of credentials' RP IDs. So there's some risk of user confusion?

A detail level consideration would be whether to have the proposed "spc prefix" contain the delimiter chars "://", because this prefix would be using arguably precious space at the beginning of the RP ID string.

It begs the question of whether the resultant prefix + rpId needs to syntactically be a serialized origin.

If not, we need some delimiter composed of char(s) that are not legal in a "valid domain string", perhaps simply ":" ...?

akshayku commented 2 years ago

I like this namespace pattern. We have something similar for CTAP in OpenSSH where RPID is being set as ssh:<>. It also allows existing authenticators to not change as well as still gives us flexibility on what we want to allow in cross-origins.

In addition to above namespace proposal, we can say that only SPC API can invoke cross-origin authentication request outside of iframes and user agent will prefix spc: automatically to the RPID being passed along. And in non-spc scenario, cross-origin authentication without iframes is not allowed.

stephenmcgruer commented 2 years ago

Thanks for thinking on this emlun (and ve7jtb)! I headed out of Web Payments TPAG meetings with action items to follow up on our hoped-for integrations with WebAuthn, but you're way ahead of me here which is amazing :)

Off-hand, the namespace idea seems like it could work for our (Web Payments) needs for SPC. I'm going to noodle on it a bit and also bring it to the next SPC task force meeting, but just wanted to acknowledge that I'm aware, appreciative, and that it has promise.

ve7jtb commented 2 years ago

SSH forces all RPID to begin with ssh: you can override the default with -O application=ssh:foo.

I think the same pattern can work for SPC. As pointed out the name appears in credential management.
It is probably a good thing to differentiate between authentication credentials and other types like payments.

We might want to choose something other than spc: such as payment: to make it clearer to users.

On the other hand, we only have one browser exposing credential management currently.

It might be possible to have the credential management UI expand spc: to something more obvious like "Card Payment"

ianbjacobs commented 2 years ago

I would not say "Card Payment" because we are not intending to limit the work to card payments. So "Payment" feels better.

Goosth commented 2 years ago

This is a great discussion.

I'd like to just ensure we're clear on the set of use-cases that an Relying Party (Bank/Account Provider/Issuer) may want to use a credential for.

If we consider banking, they would still want to use this specific credential to

Whatever solution we consider to enable this to be called from another domain should not remove/prevent those use-cases.

Limiting the SPC credential to only work cross domain or only allow payments would not be desirable, since it would severely limit its usability. For example, in 3D Secure, the cross domain SPC capability will be used by advanced merchants (with the new 3D Secure 2.3 standard), while most other merchants will still just redirect to the RP in an iFrame, where the RP will need to challenge and confirm the payment. In this second scenario, we would still want the RP to be able to enable a payment confirmation via SPC.

stephenmcgruer commented 2 years ago

This was discussed today in the SPC Task Force (part of the Web Payments WG). There were two main outcomes of the discussion:

  1. A desire that an RP should be able to access SPC in a first-party setting (e.g. on rp.com), using an existing and 'normal' WebAuthn credential. That is, to use a credential C in the following cases:

    First Party-usage Third Party-usage
    Login No bit needed Never!
    Payments No bit needed Needs a bit set at creation-time
  2. A desire that a third-party enabled credential should also be usable in a first-party context for login. That is, if rp.com creates a third-party enabled credential C so that not-rp.com can use it in a payments context, it should also be possible for a user to visit rp.com and do a login authentication flow using C.

The first of these is possible by changing the namespace solution to be about the 3p-powers rather than payment abilities (i.e3p:rp.com rather than payment:rp.com). The second of these, however, is not compatible with a namespace solution as any namespace solution is not 'backwards compatible' so to speak (i.e. deliberately one cannot use a namespaced credential as-if it were a non-namespaced one).

@ve7jtb did come up with a new proposal during the meeting, which I believe he plans to mull on and then post here if he's happy enough with it :).

christiaanbrand commented 2 years ago

It is imperative that the same WebAuthn credential can be used by the 1P (say for login to online banking) and a 3P (for authenticating a 3DS card transaction).

I might be missing something here, but I don't understand what problem we're trying to solve that the current implementation doesn't already address?

Goosth commented 2 years ago

@christiaanbrand I think we all agree on that requirement (can be used). From what we've heard, there are some RP's that would not want to 'open up' the ability to allow payments or allow 3P transactions for their tokens (e.g. an Employee authenticator).

It seems that this is not technically possible in the current design to allow all 3 of these use-cases, while still enabling RP's to indicate (during WebAuthn token creation) that they do not want these capabilities for their tokens (e.g. do not want to allow 3P invocation).

So the only way is to either

The first two are technical challenges. The last is more a risk/security/principle concept. Not sure how the community would feel about option 3, and what the potential risks are there.

cyberphone commented 2 years ago

The dependency on untrusted third-parties dealing with key handles is unique for SPC and is the result of building on authentication rather than following the industry standard, authorization.

W3C Pay does not expose key handles, except to the issuer.

ve7jtb commented 2 years ago

The current proposal of creating a new RPID namespace for credentials that can be used in the SPC 3rd party context would prevent those credentials from being used in webAuthn as authentication credentials without significant changes to webAuthn implementations.

On the SPC calls the banks have indicated that they prefer a single credential that can be flagged as also being SPC 3rd party capable.

Some people like @akshayku have indicated that they never want a plain authentication credential used in SPC.
That would also be incompatible with adding one namespace, as non 3rd party SPC credentials and authentication credentials would look the same. We would need to add two new namespaces one for 1st party SPC and one for 3rd party SPC and not use normal authentication credentials in the SPC flows. The downside of this seems to be that the RP needs to make two credentials

In principal CTAP could address UV caching and allow two credentials to be created at one time, but this will be complicated and take a long time to deploy at any scale.

The other way to approach the problem would be to use some other member of the discoverable credential to store some sort of credential type flag.

The two likely candidates that are both set by the RP and not user visible, are the userID and credblob. The RP when making the credential could add special flags to one of those members that WebAuthn would pass through and ignore. Only the SPC implementation would need to inspect those flags to see if the credential is allowed for payments and separately if it is allowed in a 3rd party context.

credBlob is a minimum 32bytes if supported so space is probably OK. Its intended application is to store a certificate hash, the other is to store a symmetric key. Probably not things you would want with a SPC credential. One issue with using this value is that the value is not exposed in the credential management API. You can however get it via get assertion without UP or UV if you have the RPID and it is created with credprotect 1 or 2. If you wanted to use this with discoverable credentials then the RP would need to create them with credprotect 1.

user.id (User Handle) is 64bytes and required for discoverable credentials. It can be interrogated both by the credential management API and by performing get assertions with UP=0 UV=0 assuming the credential was created with the correct credprotect value.

The other alternative would be to go back to the CTAP TWG and ask for a new credential-type member in CTAP2.2.
That would be incompatible with all current authenticators but could be inserted into CTAP2.1 authenticators if specified quickly. This could also be combined with using credblob/user.id only if the new member is not available in SPC.

ianbjacobs commented 2 years ago

@ve7jtb, what is needed to ask the CTAP TWG to consider this question?

ve7jtb commented 2 years ago

@ianbjacobs if a decision is taken to use a new member then it needs to go to the CTAP TWG.

If we don't change CTAP and use existing elements then the WebAuthn WG should be able to make a decision. It would be polite to let the CTAP TWG know, but there is significant overlap between the groups.

On the WebAuthn call, the preference seemed to be to find a way to do this with namespacing and not overload other members.

If we do something like adding a WebAuthn extension like the one for appID where a RP could say that it wants to use credentials in the SPC namespace for authentication that might be a way to proceed.

Essentially all credentials that are SPC capable would be created in the SPC namespace.
Normal Webauthn credentials would not be usable by SPC.

When doing authentication the RP would send the special extension and the WebAuthn client would check the spc: namespace and not the normal one.

It gets complicated in authentication when you want to check multiple RPID in one request. The CTAP2.1 spec requires separate authentications for each RPID. I need to think about how this could work. The other question is if there is a real desire by banks to have some SPC credentials that only work in the first-party context.

equalsJeffH commented 2 years ago

pedantic note: fyi/fwiw, "CTAP TWG" actual name is "FIDO2 TWG" (ie: FIDO2 Technical Working Group). CTAP is a work item of that TWG. ;-)

stephenmcgruer commented 2 years ago

Keeping folks in the loop about the WPWG's thinking: the current proposal* is to not take the 'namespace' idea and instead aim for a long-term Authenticator-based solution. (Requiring support from FIDO2 TWG and/or platform authenticators). Please take a look at that proposal.

* Not ratified by the WPWG, but does reflect recent discussions in WG meetings.

akshayku commented 2 years ago

WPWG 1st use case: Enable a relying party to use a credential for both login (in a 1p context) and SPC (by the RP, or by other parties in a 3p context).

Comment in proposal says this about namespace solution: A "namespace" proposal has been discussed on WebAuthn issue 1667. A limitation of this proposal is that it might not be straightforward to address use case 1. Because the namespace proposal does not eliminate the need for enhanced authenticator capabilities, it seems preferable just to pursue the "cross origin bit" in authenticators to address all three use cases.

I am curious about what is not straightforward in addressing use case 1? Doesn't that use case just amounts to RP always have to look for namespaced-RPID while doing the validation instead of standard RPID. This assumes that WebAuthn WG considers authentication on cross-origin to namespaced-RPID (which is also not ratified).

I am fine if long term authenticator based solution is being desired. If that's the case, then IMO, this cannot be solved in WebAuthn WG until FIDO2 TWG develops a solution which works for every authenticator (not just platform authenticators).

stephenmcgruer commented 2 years ago

I am curious about what is not straightforward in addressing use case 1? Doesn't that use case just amounts to RP always have to look for namespaced-RPID while doing the validation instead of standard RPID. This assumes that WebAuthn WG considers authentication on cross-origin to namespaced-RPID (which is also not ratified).

I think (but welcome input from others) that it is largely a question of developer ergonomics and whether one thinks they are acceptable or not. If a given RP only ever creates 1p-only xor 3p-enabled credentials, it is probably quite simple (either always pass a flag or always don't). However if they have both types (which seems feasible to me?) the RP now needs to keep track of which are which, make sure to pass the right flag for which credential they're trying to use, and (perhaps most importantly) I'm not clear how Discoverable Credentials with an empty allowList (for login) works in that case - I presume the RP can only select one namespace at a time.

In a world where we didn't need additional authenticator powers for the conditionally-shown transaction UX, I think I would agree that the namespace solution would have enough benefits (works today, backwards compatible) to be the right pick. But given the desire for some authenticator API anyway (for conditional UX support), I think the 'bake the metadata bits into FIDO' makes more sense. It also allows us to expand to other metadata bits in the future (I believe we heard from @timcappalli that that might be of interest?)

akshayku commented 2 years ago

I think (but welcome input from others) that it is largely a question of developer ergonomics and whether one thinks they are acceptable or not. If a given RP only ever creates 1p-only xor 3p-enabled credentials, it is probably quite simple (either always pass a flag or always don't). However if they have both types (which seems feasible to me?) the RP now needs to keep track of which are which, make sure to pass the right flag for which credential they're trying to use, and (perhaps most importantly) I'm not clear how Discoverable Credentials with an empty allowList (for login) works in that case - I presume the RP can only select one namespace at a time.

If an RP selects to be in this use case where they want both login as well as 3P payment credentials, then RP can choose to verify 3P namespaced RPID even for login all the time. I don't see any issue in that, except for UI.

In a world where we didn't need additional authenticator powers for the conditionally-shown transaction UX, I think I would agree that the namespace solution would have enough benefits (works today, backwards compatible) to be the right pick. But given the desire for some authenticator API anyway (for conditional UX support), I think the 'bake the metadata bits into FIDO' makes more sense. It also allows us to expand to other metadata bits in the future (I believe we heard from @timcappalli that that might be of interest?)

Conditional UX is a optional enhancement. You are only thinking about platform credentials for conditional UX. Any solution has to work with all kind of authenticators. Conditional UX has unsolved complications for security keys. Potentially unsolvable if we consider roamability nature of security keys and untrusted platform. In that case, we may have to fallback on RP making a explicit call with specific intent.

With potential new use cases, we haven't gone through pros and cons yet on having overloading single credential vs having different credentials for different use cases. Overloading multiple use cases on same credential is not that simple.

Anyway, overall it looks like if WPWG sees complications in namespace proposal, then I am afraid, we have to pause this discussion in WebAuthn WG and see what we can do in FIDO TWG which handles authenticators specific changes. This is a new requirement which will take sometime to find the right solution given the desire of multiple intents in the future. Which is fine.

stephenmcgruer commented 2 years ago

Thanks Akshay, I appreciate your input. I'll keep y'all updated as to which way the WPWG resolves, and we can then take it down whichever venue is appropriate.

Conditional UX is a optional enhancement. You are only thinking about platform credentials for conditional UX. Any solution has to work with all kind of authenticators. Conditional UX has unsolved complications for security keys. Potentially unsolvable if we consider roamability nature of security keys and untrusted platform. In that case, we may have to fallback on RP making a explicit call with specific intent.

FWIW, we have considered this a little. My thinking is a flow like this, but I acknowledge its not the smoothest experience.

akshayku commented 2 years ago

I talked to @timcappalli about his scenario which points in general desire to have multiple scenarios/intents into the future all of which can't be solved even with multiple namespace proposal.

I will think more on this, but it seems like the original proposal of new intent/scenario based approach assigned to the key seems more flexible and is the way to go for future proofing.