Open Bug 1693562 Opened 3 years ago Updated 3 months ago

WebAuthn navigator.credentials.create hangs in browser extension

Categories

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

Firefox 85
defect

Tracking

()

UNCONFIRMED

People

(Reporter: apps, Unassigned)

References

Details

(Whiteboard: [wecg])

Attachments

(1 file)

User Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:85.0) Gecko/20100101 Firefox/85.0

Steps to reproduce:

Our use case is to use WebAuthn in a Firefox extension to authenticate users.

Following the documentation we added the following code sample to our app.
See: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions

navigator.credentials
            .create({
                publicKey: {
                    challenge: stringToArrayBuffer('a1da16e81c0bdd098a04a91f853076b3785aa915ff07c1acc294e7a5d63946bc'),
                    rp: {
                        name: 'Example CORP',
                        id: '6e852fa4-0e10-4e6e-89d9-0330a4279f6f'
                    },
                    user: {
                        id: new Uint8Array(16),
                        name: 'john.p.smith@example.com',
                        displayName: 'John P. Smith'
                    },
                    pubKeyCredParams: [
                        {
                            type: 'public-key',
                            alg: -7
                        }
                    ],
                    authenticatorSelection: {
                        authenticatorAttachment: 'cross-platform',
                        requireResidentKey: true,
                        userVerification: 'discouraged'
                    }
                }
            })
            .then((newCredentialInfo) => { 
                console.log(newCredentialInfo);
            });

Actual results:

When the extension starts, the popup to use an authenticator to connect is displayed but nothing happens upon inserting and taping the authenticator (here a Yubikey).

Please see the attached screenshot.

Note that no logs were output in the browser's console until navigator.credentials.create() timeout.

Expected results:

The authenticator (here a Yubikey) should have been detected and the function navigator.credentials.create() should have resulted.

It's important to note that the rpID should be set to the uuid of the extension as the protocol moz-extension:// is not understood as a secure one (understand only https is allowed).

The Bugbug bot thinks this bug should belong to the 'Core::DOM: Web Authentication' component, and is moving the bug to that component. Please revert this change in case you think the bot is wrong.

Component: Untriaged → DOM: Web Authentication
Product: Firefox → Core

Does "browser's console" mean the console tab that's part of the Dev Tools panel (we usually call that the Web Console or Page Console) or the Browser Console that's available through the Tools menu (or Ctrl/Cmd-Shift-J)? If something's really gone wrong there might be some output on the Browser Console.

I'm new to WebAuthn but I suspect this may be a case we simply don't handle. What's the RP of an extension supposed to be? Do we follow the spec and simply check for https origins and therefore exclude extensions? According to the spec the Relying Party ID is limited to https:// origins (https://w3c.github.io/webauthn/#relying-party-identifier). There may be ways to extend this to extensions (and it would make some amount of sense in this case) and the spec does allow some wiggle room ("non-Web platforms (e.g. native mobile applications), MAY define different rules for binding a caller to a Relying Party Identifier"), but I can easily believe our implementation simply doesn't handle it.

Where are you getting the uuid you're using as the RP? I have no idea what our implementation is trying to do with extensions (if anything) but the uuid that shows up in moz-extension:// urls is generated unique per user and probably a bad choice (in safari this uuid is unique per user per session -- would never work with stored credentials). A better choice would be the extension's fixed "id" that's used in features like runtime.sendMessage() and can be obtained through runtime.id-- IF we make any attempt to handle this case.

Do you know if Chrome handles this case? If we're going to handle it we should get the behavior added to the incipient Web Extension specification and make sure the major browsers are consistent in what we think the Relying Party ID is for an extension.

This bug should probably stay in the Web Authentication component, but CC'ing some of the Web Extension folks who might be interested in how this might work.

Hello Daniel,

Thanks for your answer.

Sorry for the misunderstanding, I was talking about the console in the Dev Tools panel. That said I took a look at the Browser Console and no message showed up.

The spec is a bit blurry for non-website usage. I had this discussion with the Chromium team already (see https://bugs.chromium.org/p/chromium/issues/detail?id=1179751) and they said they follow this paragraph of the spec:

Other specifications mimicking the WebAuthn API to enable WebAuthn public key credentials on non-Web platforms (e.g. native mobile applications), MAY define different rules for binding a caller to a Relying Party Identifier. Though, the RP ID syntaxes MUST conform to either valid domain strings or URIs [RFC3986] [URL].

So on Chrome it's working well, similarly as Firefox, specifying an rpID is not mandatory to trigger the navigator.credential API flow but they will use the full path of the extension in the resulting attestation (chrome-extension://nhnjjlokanokjhheekkcgoiblhljealo).

The generation of uuid is kind of an issue. On Chrome as long as you are using a prod/published app this id is unique. On Firefox it seems generated per user. And as you said on Safari it varies per session (but that's another story).
As said before adding the uuid is not mandatory to trigger the flow (and it's likely a better idea not to reference it) but you can get it with this command browser.runtime.getURL('manifest.json');. Ultimately, this cause another problem which is that there is also a server side validation for rpID and origin. For website it's easy to use the root domain, but for extension as long as the uuid is "random" it's nearly impossible to have a strict policy (implies to use some crappy regex) (note that this is the same issue for CORS policy).

To help you investigate I created a sample project that can trigger the navigator.credentials API and allows to debug resulting attestation / assertion.
Here is a link to 2 demo videos showing how it works with Chrome and Firefox with this extension: https://files.dashlane.com/s/7ngq8dKPyC6RkJw

To help you investigate I created a sample project that can trigger the navigator.credentials API and allows to debug resulting attestation / assertion.
Missing link here: https://github.com/Mikescops/webauthn-extension-playground

For the url issue, we could end up using something like what the identity api produces.

https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/identity/getRedirectURL

We'd have to think through what else would need to happen to make this work in extension, but I think it's worth while to investigate.

Is there something we can do on our side to help you?

Hello FF team,
Following up on this, do you have any updates, or plan to work on fixing this issue?

Flags: needinfo?(dveditz)

Hello Daniel,

We're still blocked by this bug to provide WebAuthn functionality to our users, is this something that can be prioritized?

Hello FF team,
Following up on this, do you have any updates, or plan to work on fixing this issue?

Any update on this issue? I am experiencing same problem and would like to use WebAuthn from my extension.

Severity: -- → S2
Priority: -- → P4
Whiteboard: [wecg]
Priority: P4 → P3
Severity: S2 → S3
Flags: needinfo?(dveditz)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: