Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
akshayku opened this issue Aug 26, 2021 · 56 comments
Closed
Assignees

Comments

@akshayku
Copy link
Contributor

akshayku commented Aug 26, 2021

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.

  • I don't understand, how these credentials will be marked as such and be temper proof by the calling website. I think the proposal is that merchant will have all the credentialIDs and will invoke it .get() call with a new field set which says that this credential is marked as SCP compliant.
  • What is the cryptographic proof that says that this credential is created with SCP in mind? How will browser determine that one credential is allowed vs another credential is not allowed.

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
Copy link

cyberphone commented Aug 26, 2021

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
Copy link
Contributor Author

@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
Copy link

@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
Copy link
Contributor Author

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
Copy link

cyberphone commented Aug 26, 2021

@akshayku The process is approximately like this:

  • The User in some unspecified way provides a payment instrument (card number)
  • The Merchant uses that to lookup Issuer and its FIDO server
  • Using the card number the Merchant invokes the FIDO server
  • If there is an authenticator associated with the card number, SPC can be invoked, otherwise it the Merchant code must do something else

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
Copy link

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
Copy link

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
Copy link
Contributor Author

akshayku commented Aug 30, 2021

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
Copy link
Contributor

stephenmcgruer commented Aug 30, 2021

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
Copy link
Contributor

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
Copy link

cyberphone commented Aug 31, 2021

@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:

  • Redirect payment requests to the RP. This was one of the things the SPC folks (understandably) wanted to avoid.
  • Run the entire user authorization process inside of SPC in the same way as Apple Pay does. This option has never been discussed but is IMO a much better idea than building on a severely dated "Card NOT Present" architecture requiring 500 pages of documentation, certified merchant server software, and merchants becoming a part of a specific PKI in order to access bank related security services.

    (to be completely fair, registration would indeed need additional meta data like account Ids
    and logotypes to work, but the WebAuthn security model remains intact)

@akshayku
Copy link
Contributor Author

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.

  • 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.

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
Copy link

@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
Copy link
Member

emlun commented Aug 31, 2021

  • 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
Copy link
Contributor

ve7jtb commented Aug 31, 2021

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
Copy link

cyberphone commented Sep 1, 2021

@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
Copy link

cyberphone commented Sep 1, 2021

@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
Copy link
Contributor

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
Copy link
Contributor

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
Copy link

cyberphone commented Sep 4, 2021

@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
Copy link

@adrianhopebailie
Copy link

@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
Copy link

@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
Copy link
Contributor

@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 :).

  • Outside of 3DS my payment method knowledge is much poorer; I cannot think of any existing flows that would require this, but they may exist and I would look to the Web Payments WG to help us figure that out.

@cyberphone
Copy link

@ianbjacobs
Copy link

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
Copy link
Member

emlun commented Nov 2, 2021

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?

@ve7jtb
Copy link
Contributor

ve7jtb commented Nov 16, 2021

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
Copy link

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

@Goosth
Copy link

Goosth commented Nov 22, 2021

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

  • Login in to Digital banking (with discoverable credentials)
  • Confirm a Payment in the RP's 1p domain (e.g. OIDC redirect such as for Open Banking) in top level domain
  • Confirm a Payment in the RP's domain (typical of 3D Secure) inside a 3rd Party iFrame

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
Copy link
Contributor

stephenmcgruer commented Nov 22, 2021

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 :).

@equalsJeffH equalsJeffH changed the title Cross origin authentication without iframes Cross origin authentication without iframes (accommodating SPC in WebAuthn) Nov 22, 2021
@christiaanbrand
Copy link

christiaanbrand commented Nov 29, 2021

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
Copy link

Goosth commented Nov 30, 2021

@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

  • Find a way to enable the usage attributes to be set during creation
  • Find a way to create multiple tokens each with a specific attribute (e.g. token for 1P and separate token for 3P)
  • Remove the restrictions and always enable all tokens for these 3 use-cases.

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
Copy link

cyberphone commented Nov 30, 2021

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
Copy link
Contributor

ve7jtb commented Dec 1, 2021

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
Copy link

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

@ve7jtb
Copy link
Contributor

ve7jtb commented Dec 2, 2021

@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
Copy link
Contributor

equalsJeffH commented Dec 2, 2021

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
Copy link
Contributor

stephenmcgruer commented Dec 14, 2021

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
Copy link
Contributor Author

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
Copy link
Contributor

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
Copy link
Contributor Author

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
Copy link
Contributor

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
Copy link
Contributor Author

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.

@ve7jtb
Copy link
Contributor

ve7jtb commented Dec 15, 2021

Unless we find some other field in a discoverable credential to store the canBeUsedFor3PSPC flag, I see there basically being two options.

  1. all 3P credentials are created in a different RPID namespace.
  • The main problem with this is UX when the RP is trying to use some mix of 1P and 3P credentials for authentication. The browser may need to do multiple UV actions to be able to sort through the two RPID values. If the RP was willing to not use 3P credentials for authentication, or only 3P credentials for authentication this could work.
  1. Use only 1P credentials at the CTAP layer. If a RP wants to flag a credential as 3P for SPC then that flag would be local to the particular browser instance the credential was created on. That is basically what we have in the current pilot. The difference is that in the 1P SPC flow any credential roaming or platform could be used now. The 3P credentials being used cross-browser and device will need to be deferred to CTAP2.2 for a solution. That will probably add one to two years to the timeframe for a broad deployment of the 3P credentials in a cross-browser way.

Neither solution seems to be all that the banks are asking for. However we are trying to adapt an existing platform to the new requirements. It is not surprising that some compromise is required.

I guess the advantage of the second option is that it is OK for the 1P use case that seems to be the highest priority and will work with some limitations for 3P SPC in the short term and will work fully after updates.

The namespace option is a bit of an ugly hack that has no easy fix going forward so will haunt us for a long time.
The one advantage is that it would work with existing authenticators at the cost of RP flexibility.

If CTAP2.2 prioritized this and the new purpose flag field is small enough to put in the credentialID we could see prototypes in 2022. I don't know how long it would take the platform authenticators to change. We tend to assume they are just software so could change quickly. I have yet to actually see that happen with any of them:) So option 2 would take time before it would work cross-browser. Depending on the number of browsers planning on supporting SPC this might be an acceptable compromise.

@emlun
Copy link
Member

emlun commented Jan 10, 2022

One thing we discussed a bit on the 2021-12-15 call: there's some risk of introducing a (weak) de-anonymization attack vector here. Say a malicious website wants to confirm a guess at someone's identity, and knows some of their SPC credential IDs. The malicious website could nag the victim with an SPC prompt to authorize a payment of $0 or something, until the victim agrees just to get rid of it. The malicious website has now successfully identified the victim, and the important point here is that the victim never registered to the malicious site. This kind of attack is currently possible only on the domain where the credential was created, but cross-origin credentials could be vulnerable to this on any domain.

It's a weak attack since the attacker needs to already know the victim's credential IDs, but this does mean that SPC/cross-origin credentials would have (slightly) weaker privacy guarantees than "first-party"/"same-origin" credentials (all current WebAuthn credentials). Especially since SPC as currently proposed shares credential IDs across domains, significantly increasing their exposure.

The main mitigation I can see is if RPs have to actively opt in to cross-origin credentials, and ideally not by a single binary setting but by an allow-list of domains (either a static list or a dynamic query like how Access-Control-Allow-Origin works in CORS). That wouldn't prevent the attack, strictly speaking, but it would limit the attack surface to some set of "trusted" origins defined by the credential issuer. Although that set might in practice end up being "allow any domain" in many cases anyway...

@stephenmcgruer
Copy link
Contributor

Acknowledging that this issue has been long and contains many sub-discussions and proposals, I wanted to be clear on what we (WPWG) think are the next steps here.

At this point, we believe that we need authenticator-level support for the following two things:

  1. At creation time, the ability to ask the authenticator to set a bit in the credential, indicating that the credential may be used cross-origin for SPC.
  2. At authentication time, mechanism(s) to ask an authenticator (or to determine directly from a credential ID), without user interaction with the device:
    1. If a credential is SPC-enabled.
    2. If a credential is available on the authenticator. (We believe that this similar to that which is required for the WebAuthn Conditional UI Proposal.)

(Note that the above presumes that SPC in a 1p context will always be available, and that the bit will indicate that it is also allowed from a 3p context. As always, login will never be allowed from a 3p context.)

As we understand it, these require CTAP level changes, so our next step is to send a proposal to the FIDO2TWG for these, within the next 2 weeks. Please feel free to give us any input before we move to do that :).

@ve7jtb
Copy link
Contributor

ve7jtb commented Mar 7, 2022

Based on a credentialID the platform can determine if that credentilID exists on the authenticator assuming that it is not created at credprotect level 3. In principal the flag could be reported in an extension as part of the normal get assertion with UV=0 UP=0. We could also do something with credential management, however that currently requires authentication.

It gets more complicated if there is a requirement for this to work without an allow list.
Without the credential ID you would need an authentication if the credentials are created at credprotect level 2 (The default in Chrome)

One option would be to always create cross-origin capable credentials at credprotect level 1. That would allow them to be discovered without forcing a user verification first.

That was the original design but the Google privacy team wanted to enforce some sort of authentication before relating the information as I bleve they consider the RPID storage to be sensitive. @agl will have better info on those concerns that might resurface if we start making discoverable credentials at L1.

Not a problem if there is always an allow list.

John B.

@stephenmcgruer
Copy link
Contributor

Not a problem if there is always an allow list.

The SPC spec currently requires an allowList (we called it credentialIds), so the short term seems ok.

Thinking long term - my gut feel is that 'we' (everyone) wouldn't want discoverable credentials to work cross-origin as it feels even more dicey security/privacy wise; but I may be wrong.

@akshayku
Copy link
Contributor Author

Closing this issue also as SPC is already incorporating WebAuthn today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests