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

Improved version of extension for Transaction Confirmation #2020

Open
wants to merge 24 commits into
base: main
Choose a base branch
from

Conversation

rlin1
Copy link
Contributor

@rlin1 rlin1 commented Feb 8, 2024

supporting security keys or platform authenticators to show the transaction. Also supports the platform to show the transaction text.
If the client displayed the transaction text but not the authenticator (for example when using a security without display), the transaction text will be only included in the collectedClientData - similar to what SPC is doing.
If the authenticator showed the transaction text, it will also be included in the extension that was signed by the authenticator (known and potentially attested entity showed the transaction text as opposed to a unknown client).


Preview | Diff

@rlin1 rlin1 self-assigned this Feb 8, 2024
@rlin1
Copy link
Contributor Author

rlin1 commented Feb 8, 2024

To be decided: should we change the extension name back to txAuthSimple?
Pro: Authenticators that implemented it would still work and don't need a change.
Can it harm: Don't think so. Clients never practically supported the extension and the functionality change relates to the clients.

@rlin1
Copy link
Contributor Author

rlin1 commented Feb 14, 2024

Close #2022

@rlin1 rlin1 linked an issue Feb 14, 2024 that may be closed by this pull request
@emlun emlun self-requested a review February 14, 2024 19:18
@timcappalli
Copy link
Member

@christiaanbrand or @rlin1 can you join a WebAuthn WG call in March to discuss this?

@nadalin nadalin added the @Risk Items that are at risk for L3 label Feb 28, 2024
@FlxMgdnz
Copy link

We would love to see this extension added to L3 and get browser/OS support. It is fundamentally relevant - even crucial - for any PSD2 regulated bank and other financial institutions.

@rlin1
Copy link
Contributor Author

rlin1 commented Feb 29, 2024

@christiaanbrand or @rlin1 can you join a WebAuthn WG call in March to discuss this?

I plan to join the call on March 6th.

@petrdvorak
Copy link

I want to vouch for this for the reason already mentioned - without the ability to send transaction data to an authenticator in a way it can display them to the user (what you see is what you sign), achieving compliance in banking will be difficult for any FIDO2-related efforts. Standards such as Secure Payment Confirmation help a bit, but having the extension available would be much appreciated.

@mage28
Copy link

mage28 commented Mar 8, 2024

Most important stuff has already been mentioned by @rlin1, @FlxMgdnz and @petrdvorak. Thank you!
Having the option to send/display some data (ideally) on the authenticator would be greatly extend the usage for FIDO2/Passkey beyond authentication/sign-in usecases and open it up, e.g. for financial usecases (regulated by PSD2) that require the secure display of transaction details. But it is actually helpful for all usecases where it makes sense to show a user a compact information WHAT he is actually doing, in a way that is almost impossible to modify by malware and such.

@petrdvorak
Copy link

petrdvorak commented Mar 8, 2024

Maybe one more "storytelling comment" on this...

When we started working on our FIDO2 HW token about two years ago, I read through the FIDO2 documents and thought: "This is great. We can send a challenge to an authenticator, and it will sign it."

Then we started implementing things and found out that clientDataJSON, which actually contains the challenge, is essentially useless as the bearer of the data, as it is sent to the authenticator ironed out via SHA256 hash. While I understand the need for efficiency in interfaces like NFC/Bluetooth/USB (after all, some enterprises probably still run their COBOL apps on Windows 95), this is a neat candidate for abstraction in the standard so that we can decide to send clientDataJSON as a plain-text form to the authenticator, rather than hash and use the challenge itself for the WYSIWYS purpose.

From the specification, I understand the clientDataJSON structure is the following:

dictionary CollectedClientData {
    required DOMString           type;
    required DOMString           challenge;
    required DOMString           origin;
    DOMString                    topOrigin;
    boolean                      crossOrigin;
};

So, practically, it is something like this (non-minified, intentionally randomly found a bank with a long name, and used long challenge):

{
   "type": "webauthn.get",
   "challenge": "cb48493c-a0c7-4a9d-9aed-a172724d4357&A1*A100CZK*ICZ2730300000001165254011*D20180425",
   "origin": "moldindcondbank.md",
   "topOrigin": "moldindcondbank.md",
   "boolean": false
}

Is this so horrible in terms of size? I mean... the SHA256 hash almost makes the payload longer. ;-)

@prusnak
Copy link

prusnak commented Mar 10, 2024

Any thoughts on this @andrewkozlik?

@petrdvorak
Copy link

Maybe one more comment from my side after extensive reading on this subject (apologies, but I am fascinated that a challenge-response protocol does not allow sending the challenge to the authenticator in plain form, or at least augment it with custom data).

From what I understood, one of the reasons why web browser vendors did not implement txAuthSimple extension was that they did not want to display data provided by the relying party (web page) in the browser UI. We can live without this - no need to display anything. This is why we added a display to our authenticator. The user can only see the challenge data / associated data in the authenticator - we are OK with this. We just need a way to sneak structured data to the authenticator.

I still think the best way to do this is not to destroy the challenge object by hashing it, but having an extension that works the best effort is enough.

@FlxMgdnz
Copy link

Maybe one more comment from my side after extensive reading on this subject (apologies, but I am fascinated that a challenge-response protocol does not allow sending the challenge to the authenticator in plain form, or at least augment it with custom data).

From what I understood, one of the reasons why web browser vendors did not implement txAuthSimple extension was that they did not want to display data provided by the relying party (web page) in the browser UI. We can live without this - no need to display anything. This is why we added a display to our authenticator. The user can only see the challenge data / associated data in the authenticator - we are OK with this. We just need a way to sneak structured data to the authenticator.

I still think the best way to do this is not to destroy the challenge object by hashing it, but having an extension that works the best effort is enough.

I agree that it would be a good first step to simply hand over tx data to authenticators and enable scenarios where dedicated hardware authenticators with display capabilities can be used. Ultimately, we should aim for platform support, as this will have a much bigger impact.

From what I remember, there were concerns about tx data formatting and encoding, which need to be handled in secure context where you'd want as little of such complexity as possible. So the challenge is to define a format that is comprehensive enough for a user to understand what they are signing off, but simple enough for the platform providers' implementation teams to follow.

Windows hello txAuth

@rlin1
Copy link
Contributor Author

rlin1 commented Mar 13, 2024

Consider using a short name for the extension "conf" - instead of "confirmation".

index.bs Outdated Show resolved Hide resolved
@petrdvorak
Copy link

petrdvorak commented Mar 13, 2024

Consider using a short name for the extension "conf" - instead of "confirmation".

... configuration... conference... You might be overthinking it, keep the name descriptive. 😊

Edit:

strlen('txAuthSimple')
12

strlen('confirmation')
12

@petrdvorak
Copy link

Is introducing the confirmation length limit (1024 bytes?) helpful or harmful? What do you think?

@rlin1
Copy link
Contributor Author

rlin1 commented Mar 14, 2024

Is introducing the confirmation length limit (1024 bytes?) helpful or harmful? What do you think?

likely helpful. Potentially even shorter...

@mage28
Copy link

mage28 commented Mar 14, 2024

Is introducing the confirmation length limit (1024 bytes?) helpful or harmful? What do you think?

Characters or bytes? Practically 1024 is more than sufficient, probably you will need to stick with very short and clear text informations, probably of less than 100 or 200 characters. So setting a max length limit of 1024 is surely not harmful for all usecases I can imagine and sets some technical restrictions. It can potentially be even shorter, but then we start to discuss when it starts to hurt the one or other.

@petrdvorak
Copy link

@mage28 We are looking at this from the connected authenticator perspective, so bytes are a bit better measure of the data transfer limit. For our use case, the typical message will be much shorter. Even rich transaction details are shorter, i.e.:

Please approve a recurring payment of 43,289.99 EUR from an account
FI211234569876543210 to account IE64BOFI90583812345678, payment
reference: 9458711390468640.

(160 characters)

Note: PSD3 might change the scope of dynamic linking, so that the authentication code is linked to an amount, currency, destination account, and source account, at least.

@prusnak
Copy link

prusnak commented Mar 14, 2024

256 or 512 or 1024 bytes (not chars) including the zero terminator char, please.

That is 255 or 511 or 1023 printable bytes.

This will make the implementation so much easier for constricted embedded environments.

@petrdvorak
Copy link

@prusnak Reading through the conversation, this will primarily be about platform authenticators. Also, regarding the "confirmation" naming semantics, I read it as "it is the text the user can see in Windows UI alongside the standard confirmation window"). As a result, the JavaScript code will likely work by just providing a text... I would suggest keeping this USVString ("characters") and trimming the limit to 256 characters (which is plenty, as my example above suggests). UTF-8 encoding will result in at most 1024 bytes and will fit the zero terminating byte, or will fill the limit (CTAP protocol should hopefully take care of working with the data as bytes).

index.bs Outdated Show resolved Hide resolved
index.bs Outdated Show resolved Hide resolved
index.bs Outdated Show resolved Hide resolved
index.bs Outdated Show resolved Hide resolved
index.bs Outdated Show resolved Hide resolved
index.bs Outdated Show resolved Hide resolved
index.bs Outdated Show resolved Hide resolved
index.bs Outdated Show resolved Hide resolved
index.bs Outdated Show resolved Hide resolved
@petrdvorak
Copy link

To continue our efforts to implement WYSIWYS in the connected authenticator: We found that besides not having txAuthSimple, even hmac-secret is not implemented as expected.

We were a bit desperate, as we really needed to get the data to the connected authenticator device so that the user could confirm it... and we managed to hack it.

By only supporting non-discoverable credentials, we get the list of allowCredential in WebAuthn, and - voila - this is the only data bundle we can pass in the authenticator and obtain it without modifications. So, we now append our challenge to the credential ID. Our authenticator can interpret this. Other authenticators don't need to care. Credential ID is not them. We then also compute a proprietary signature response (still conforming to ES256), binding the "plain challenge" we get in allowCredential list to the "hashed challenge" constructed from ClientDataJSON by the WebAuthn protocol... Cool, it works. It is ugly. But it works. We can do better...

Introducing "WebAuthn2: This time, we will get it right.", starring Steven Segal.

The signable challenge is in Verifiable Credentials format so that it is signed by the relying party, and the browser (or connected authenticator) can display it, as it is a standard format. Then, signing the challenge in the authenticator (platform or cross-platform) results in a Verifiable Presentation.

Is there any effort alongside this outline?

@rlin1 rlin1 requested a review from emlun April 29, 2024 10:11
index.bs Outdated
Comment on lines 7617 to 7625
:: 1. use a dialog to the user that makes the user aware of the confirmation to be provided (as opposed to doing a simple sign in).
1. display the confirmation prompt to the user. The client SHOULD
indicate that the confirmation prompt originates from a specific relying party
(as opposed to the platform itself).

1. use the {{CollectedClientConfirmationData}} structure containing the confirmation prompt instead of using the {{CollectedClientData}} structure.

1. pass-through the extension to the authenticator (see "client extension output" below)
1. pass-through the "authenticator extension output" to the caller as part of the assertion
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: sentences should start with capital letters.

:: [=authentication extension|Authentication=]

: Client extension input
:: A single USVString confirmationPrompt. This string might contain the following formatting tags: <code>&lt;b&gt;&lt;/b&gt;</code> to mark the text inbetween as bold and <code>&lt;br /&gt;</code> to force a line break. Support of these formatting tags is "best effort". Implementations not supporting it SHALL NOT display the tags in "verbatim".
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to get trimmed down to just confirmation:

Suggested change
:: A single USVString confirmationPrompt. This string might contain the following formatting tags: <code>&lt;b&gt;&lt;/b&gt;</code> to mark the text inbetween as bold and <code>&lt;br /&gt;</code> to force a line break. Support of these formatting tags is "best effort". Implementations not supporting it SHALL NOT display the tags in "verbatim".
:: A single USVString confirmation. This string might contain the following formatting tags: <code>&lt;b&gt;&lt;/b&gt;</code> to mark the text inbetween as bold and <code>&lt;br /&gt;</code> to force a line break. Support of these formatting tags is "best effort". Implementations not supporting it SHALL NOT display the tags in "verbatim".

@akshayku akshayku self-requested a review May 15, 2024 19:29
index.bs Outdated

1. Verify that the `confirmation` key exists in the [=authData/extensions=] in |authData|.
1. Verify that the `confirmation` value in the [=authData/extensions=] in |authData| equals the confirmation prompt that is expected (i.e., that was used when requesting the `confirmation` extension).
1. If processing a response without the `confirmation` extension is acceptable by policy: Fall back to <code>|credential|.{{PublicKeyCredential/response}}.{{AuthenticatorResponse/clientDataJSON}}</code> entry if authenticator extension output is absent.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy-pasting offline chat with @rlin1

How does the extension processing work when uv is preferred or required. Does the authenticator/client need to show two prompts?

It is up to the relying party to handle the different user verification options appropriately. This includes appropriate settings for userVerification and appropriate processing of UV and UP. This confirmation extension doesn’t change the way user verification is handled by the client platform / authenticator. Have added a note regarding this.

If the authenticator does not support displaying the confirmation prompt but supports signing the confirmation, does the browser/OS take over this responsibility? Do we need corresponding changes in CTAP to let providers indicate to the browser/OS whether this extension is fully/partially supported.

In that case the authenticator doesn’t support the confirmation extension. The client platform will add the confirmation details to the collectedClientData structure so that any authenticator would just sign over it- The relying arty can detect that by not finding the confirmation extension in the assertion, but only seeing the confirmation details in the collectedClientData.

“If processing a response without the confirmation extension is acceptable by policy” – Not sure what this means. How does an RP specify that confirmation prompt is optional. And if the confirmation is optional then it does not provide auditable evidence that consent was visible to the user as you stated below.

It is up to the relying party to decide whether or not to accept an assertion without the confirmation extension (but with confirmation details in the collected clientData). This situation indicates that a privileged component (i.e. client platform) has shown the confirmation details, but it wasn’t done by the authenticator itself (which could be an attested component).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the approach of letting RPs decide whether to accept an assertion without confirmation makes sense but its not clearly called out in the PR. We should further clarify here that if authenticator does not support the confirmation extension, the confirmation string is still signed over.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be addressed by commit 9f2723f

@nadalin nadalin added this to the Futures (catch-all) milestone Jun 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@Risk Items that are at risk for L3 type:technical
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Revised txAuthSimple extension