Open Bug 1863819 Opened 1 year ago Updated 14 hours ago

Support WebAuthn PRF extension

Categories

(Core :: DOM: Web Authentication, enhancement, P3)

enhancement

Tracking

()

ASSIGNED

People

(Reporter: jschanck, Assigned: emlun)

References

(Depends on 1 open bug, Blocks 1 open bug)

Details

(Keywords: dev-doc-needed)

Attachments

(18 obsolete files)

See Also: → 1593571

Hi, thanks for the links everyone, I've added more here: https://github.com/mozilla/standards-positions/issues/798#issuecomment-2022270761

I'd like to see PRF finally implemented in Firefox too. In Chrome it's there and PRF can be used for Passkeys with Okta and even with Bitwarden.

Okta is a single-sign on solution used by many large enterprises that is also integrated with Google Workspaces and other applications.

This is a graphical, gentle interactive introduction for learning how the WebAuthn API works: https://webauthn.guide/#registration
See https://levischuck.com/blog/2023-02-prf-webauthn for a demonstrator test site for testing the PRF extension implementation.

It shows and describes a node.js library and app for testing: https://www.passkeys.com/guides It should help to understand what needs to be implemented and the site can be used for testing. It is functional with Chrome:

Testing the Registration: https://levischuck.com/blog/2023-02-prf-webauthn#heading-registration
Using Chrome, clicking the button "Register" opens the registration of a username for this demonstration site. If the Bitwarden extension is enabled, the passkey is registered (saved) by the Bitwarden extension (otherwise by Windows Security using a device or Windows Hello).

Testing the Authentication: https://levischuck.com/blog/2023-02-prf-webauthn#heading-authenticate
Using Chrome, clicking the button "Retrieve PRF" opens the confirmation of using the passkey to authenticate with the demonstration site. If the Bitwarden extension is enabled and the passkey for the site is registered, the the Bitwarden extension offers to confirm the passkey, otherwise by Windows Security should do the same using a device or Windows Hello.

This is where I see that PRF is requested in the options navigator.credentials.create(options); for user registration using PRF in the example code shown on the site:

    // Important part: the extensions!
    extensions: {
      // WebAuthn uses the same structure for registration
      // as authentication.
      // While it looks like we are asking the authenticator
      // to evaluate a PRF over the salt, this is more
      // of a not equals null, not empty check that sets
      // the authenticator up for future PRF use.
      prf: {
        eval: {
          first: state.salt,
        },
      },

The answer if PRF is supported is then checked in the code here:

// See if PRF is supported or not
const extensionResults = regCredential.getClientExtensionResults();
if (extensionResults?.prf?.enabled) {
  state.prfSupported = true;
} else {
  state.prfSupported = false;
}

The option prf (shown for registration above) is also used when asking for authentication using PRF by navigator.credentials.get(options);:

// Ask the browser to find and authenticate with the selected credential
const authCredential = await navigator.credentials.get(options);

For PRF, navigator.credentials.create() and navigator.credentials.get() would have to talk to the authentication extension (like Bitwarden or Windows Hello) for saving (registering) the passkey and for confirming authentication at the site using the passkey.

Some links on PRF: https://github.com/forcedotcom/cli/discussions/2482

AFAICS, these are the API functions that are called here:
https://developer.mozilla.org/en-US/docs/Web/API/CredentialsContainer/create
https://developer.mozilla.org/en-US/docs/Web/API/CredentialsContainer/get

And according to this page, a huge part of the WebAuthn API is already implemented:
https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API

Compared to that, PRF looks like a miniscule detail that is missing, but it would finally add that missing piece that makes it all work much more often.

I guess that the interfacing from to authentication extension should already be implemented for WebAuthn without PRF, so (I guess) hopefully, only the addition of authentication using PRF needs to be added.

Of course the https://w3c.github.io/webauthn/#prf-extension is needed for the actual implementation, but also the existing infrastructure where the PRF extension would be added would be of interest.

One aspect that looks to be like an essential hint is this sentence near the end of the site:

Second, navigator.credentials must be protected from local and extension scripts, else the PRF Extension evaluation may be exfiltrated.

Are these preconditions in place so PRF can be implemented?

Flags: needinfo?(jschanck)

In the Chromium PRF ticket at https://issues.chromium.org/issues/40140659#comment21, this test suite was used: It has 3 different PRF buttons and the buttons report the test result: https://securitykeys.info/ts/test_suite.html

Another PRF test app: https://passkeys.fission.app/register
And here is the initial Passkeys ticket: https://bugzilla.mozilla.org/show_bug.cgi?id=1792433

PS: This is the discussion thread in the Bitwarden forum about PRF:
https://community.bitwarden.com/t/sign-into-bitwarden-with-a-passkey-google-apple-microsoft/41053

Are these preconditions in place so PRF can be implemented?

There is nothing that would prevent us from implementing PRF easily. However, the PRF extension is not a high priority for us at this time.

Flags: needinfo?(jschanck)

I've been using Firefox to prototype some other WebAuthn extensions, and as part of that ended up needing to implement the PRF extension too. So, I have a prototype implementation of the PRF extension in Firefox. Would Mozilla like me to contribute my implementation? It's fairly immature at the moment (no tests, probably doesn't cover all platforms, probably quite ugly IDL model, etc.), but I've at least verified that it works and gives the same results as Chrome, and I'd be happy to take it through the process to get it to maturity. What do you think?

:emlun, I'm happy to take a look at your patch. Please submit it with moz-phab.

Patch path of authenticator dependency for local dev

Assignee: nobody → emil
Status: NEW → ASSIGNED

Implement prototype of WebAuthn PRF extension support

Send correct PIN protocol ID in hmac-secret

Before this change, OpenSK (tag 2.1, commit
893faa5113f47457337ddb826b1a58870f00bc78) returns CTAP2_ERR_INVALID_PARAMETER in
response to attempts to use the WebAuthn PRF extension.

Sorry for the delay, but I've now submitted my prototype implementation. As I mentioned I'm sure this will need some iteration as I'm completely new to the process and to Firefox conventions (in particular, I'm fairly sure the first commit ("Patch path of authenticator dependency for local dev") shouldn't really be there).

Anyway, please take a look and see if this seems like a sensible start. I haven't tested this on other platforms than Linux, so presumably some parts are missing for the respective Windows/Mac backends? What automated tests would make sense to add for this?

This reverts commit a6fdf4fb3b06e5f3bfea4053d4c600e21766535e.

Add support for WebAuthn PRF extension in authenticator-rs

Send correct PIN protocol ID in hmac-secret

Before this change, OpenSK (tag 2.1, commit
893faa5113f47457337ddb826b1a58870f00bc78) returns CTAP2_ERR_INVALID_PARAMETER in
response to attempts to use the WebAuthn PRF extension.

Attached file Bug 1863819 - Revert Firefox changes (obsolete) —

Patch path of authenticator dependency for local dev

Implement prototype of WebAuthn PRF extension support

Attachment #9403417 - Attachment is obsolete: true
Attachment #9403743 - Attachment is obsolete: true
Attachment #9403744 - Attachment is obsolete: true
Attachment #9403746 - Attachment is obsolete: true
Attachment #9403755 - Attachment is obsolete: true
Attachment #9403756 - Attachment is obsolete: true

./mach clang-format -p dom/webauthn/WebAuthnArgs.cpp dom/webauthn/PublicKeyCredential.h dom/webauthn/WebAuthnManager.cpp dom/webauthn/PublicKeyCredential.cpp dom/webauthn/WebAuthnResult.cpp dom/webauthn/WebAuthnArgs.h dom/webauthn/WebAuthnTransactionParent.cpp

Sorry for the noise as I'm figuring out Phabricator! I've now separated the authenticator-rs changes from the Firefox ones, so the Phabricator stack is now a series of five commits: two commits to be transplanted to authenticator-rs, one to revert (patching the local crate path), one with the substantive Firefox changes and one fixing the C++ formatting errors.

I anticipate needing to reorganize the stack again later to abandon the authenticator-rs commits, but I'll await instruction before doing so.

Attachment #9403745 - Attachment description: Bug 1863819: Support WebAuthn PRF extension r=jschanck → Bug 1863819 - Add support for WebAuthn PRF extension in authenticator-rs
Attachment #9403418 - Attachment description: Bug 1863819: Support WebAuthn PRF extension r=jschanck → Bug 1863819 - Send correct PIN protocol ID in hmac-secret
Attachment #9403416 - Attachment description: Bug 1863819: Support WebAuthn PRF extension r=jschanck → Bug 1863819 - Patch path of authenticator dependency for local dev
Attachment #9403757 - Attachment description: Bug 1863819: Support WebAuthn PRF extension r=jschanck → Bug 1863819 - Implement prototype of WebAuthn PRF extension support
Attachment #9403745 - Attachment description: Bug 1863819 - Add support for WebAuthn PRF extension in authenticator-rs → Bug 1863819 - Add support for WebAuthn PRF extension in authenticator-rs r=jschanck
Attachment #9403418 - Attachment description: Bug 1863819 - Send correct PIN protocol ID in hmac-secret → Bug 1863819 - Send correct PIN protocol ID in hmac-secret r=jschanck
Attachment #9403416 - Attachment description: Bug 1863819 - Patch path of authenticator dependency for local dev → Bug 1863819 - Patch path of authenticator dependency for local dev r=jschanck
Attachment #9403757 - Attachment description: Bug 1863819 - Implement prototype of WebAuthn PRF extension support → Bug 1863819 - Implement prototype of WebAuthn PRF extension support r=jschanck
Attachment #9403761 - Attachment is obsolete: true
Attachment #9403745 - Attachment is obsolete: true

This should be (and is) done in ParseCreationOptionsFromJSON, but not in
ParseRequestOptionsFromJSON.

Attachment #9403418 - Attachment is obsolete: true
Attachment #9403416 - Attachment is obsolete: true
Keywords: dev-doc-needed
Depends on: 1909962

Is there anything more that needs to happen for Firefox to support this beyond updating to the new authenticator-rs 0.4.0 release?

The commits in Phabticator need to be rebased and it seems that some tests are missing

This is based on Emil Lundberg's work in D211535. I've just wired up the
virtual authenticator, updated the web-platform test expectations, and made a
few stylistic changes and bug fixes.

Attachment #9403757 - Attachment is obsolete: true
Attachment #9407303 - Attachment is obsolete: true
Attachment #9407305 - Attachment is obsolete: true
Attachment #9407306 - Attachment is obsolete: true
Attachment #9407307 - Attachment is obsolete: true
Attachment #9439492 - Attachment description: WIP: Bug 1863819 - support for the WebAuthn PRF extension when using authenticator-rs. r=keeler → Bug 1863819 - support for the WebAuthn PRF extension when using authenticator-rs. r=keeler
Attachment #9440092 - Attachment description: WIP: Bug 1863819 - support for the WebAuthn PRF extension on Windows. r=keeler → Bug 1863819 - support for the WebAuthn PRF extension on Windows. r=keeler

Comment on attachment 9407302 [details]
Bug 1863819 - Delete hmacCreateSecret input parsing from ParseRequestOptionsFromJSON

Revision D213626 was moved to bug 1935276. Setting attachment 9407302 [details] to obsolete.

Attachment #9407302 - Attachment is obsolete: true
Depends on: 1935277
Depends on: 1935278

Comment on attachment 9439492 [details]
Bug 1863819 - support for the WebAuthn PRF extension when using authenticator-rs. r=keeler

Revision D230004 was moved to bug 1935277. Setting attachment 9439492 [details] to obsolete.

Attachment #9439492 - Attachment is obsolete: true

Comment on attachment 9440092 [details]
Bug 1863819 - support for the WebAuthn PRF extension on Windows. r=keeler

Revision D230316 was moved to bug 1935278. Setting attachment 9440092 [details] to obsolete.

Attachment #9440092 - Attachment is obsolete: true
Depends on: 1935280

I am excited to see progress on this! I see that there are individual issues for Windows and macOS support. What about Linux? Is that already implemented in the code that was just merged?

Yes, Linux support was merged in Bug 1935277. In general that patch added PRF support for any platform where we use the authenticator-rs library to interact with security keys.

Great, thanks for clarifying that. I presume from the recent creation of https://bugzilla.mozilla.org/show_bug.cgi?id=1835410 that Firefox doesn't use authenticator-rs on macOS? I'm guessing that Firefox is using some platform-specific passkey API on macOS? As far as I can tell, implementation for PRF support on macOS has not started, is that right?

Thank you John for finishing Bug 1935277! Sorry for never getting back to it, I was fully occupied for the last few months. But I'm excited to see this moving forward. Thanks again!

Thank you for implementing this feature!

Do I have to enable the PRF extension first or is the feature not yet included in Firefox 135.0?

I wanted to test the PRF extension on the website https://levischuck.com/blog/2023-02-prf-webauthn with the release of Firefox 135.0 using Windows , but I only get {} as a result when registering. With Chrome and Edge I get the following result:

{
  “prf": {
    “enabled": false
  }
}

The reason why I get “enabled": false as a result with Chrome and Edge is that Windows Hello does not yet support the PRF extension.

The fix in bug 1935277 applies to the "authenticator-rs" pathway, which is our library for talking to USB security tokens. We only use that on platforms where we don't have OS support for WebAuthn (i.e. Linux). If you disable Windows Hello (in Windows itself) I think we might still fallback to that library to support security tokens on Windows, but that's obviously not the usual or intended configuration.

Thank you for the information!

I’ve discovered that it works with the default configuration when I store the passkey in an authenticator that supports the PRF extension, specifically by saving it on an iOS device using the QR code passkey flow via CTAP/BLE, instead of storing the passkey in Windows Hello. In this case, I get the following result:

{
  "prf": {
    "enabled": true
  }
}

It appears that if the authenticator does not support the PRF extension, Firefox fails to pass it through properly and instead returns an empty object ({}). In contrast, Chrome and Edge - even if the authenticator used (such as Windows Hello) does not support the PRF extension - still forward the PRF parameter to the WebAuthn application (with "enabled": false), thereby explicitly communicating the absence of PRF support.

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: