w3c / webauthn

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

Extend WebAuthn spec to support interoperability in WebExtensions #1766

Closed Mikescops closed 2 years ago

Mikescops commented 2 years ago

Background

We, at Dashlane, a password manager, use WebAuthn to provide passwordless authentication with the fingerprint or 2FA using a roaming authenticator in order to log in to the user's vault. For instance, a user can decide that their vault will be decrypted by a combination of their Master Password and a remote key that is delivered against a valid WebAuthn flow. If you want to have more context, I recommend Dashlane's whitepaper. We use this flow in a WebExtension as it is our main app.

Issue

I already raised this issue a year ago in thread #1372 but never formalized it in its own issue. Currently, the spec doesn't mention the use of WebAuthn inside a WebExtension, but as a matter of fact, the API is accessible in this context (except for Firefox where the implementation is still broken: bugzilla thread).

WebAuthn relies on the validity of the RPID (+ its origin). In the context of a WebExtension, the browser is setting the RPID to the current URL which looks like this chrome-extension://dnifbcdaadaoifdojfdjhimhdaaoomio. This causes interoperability issues with other platforms when it comes to roaming authenticators as the chrome-extension pattern is not matching your website domain.

Proposal

Context: To quote @dwaite :

With the example of an application, let's call it AsteriskAsterisk. There is a desire to authenticate access with WebAuthn. The existing model would be:

  • A web-based version may have an RPID based on its hosting, perhaps "asteriskasterisk.com" PWA functionality which allows that web version to behave like an installed application would use the same RPID of "asteriskasterisk.com"
  • A native application on android or windows would use a RPID of "asteriskasterisk.com" (after some sort of application linking to the domain to whitelist the native apps)
  • A CLI version, if the platform allows direct usage of a FIDO authenticator or if it uses the same OS-level whitelisting above, would use the RPID of "asteriskasterisk.com"
  • A browser extension should therefore be defined to use a RPID of (you guessed it) "asteriskasterisk.com".

Solution: Similar to the implementation of the FIDO2 API for Android, WebExtensions should support interoperability with your website by defining your extension ID in a .well-known (like https://asteriskasterisk.com/.well-known/assetlinks.json) hosted on your domain name.

For instance:

[
  {
    "relation" : [
      "delegate_permission/common.handle_all_urls",
      "delegate_permission/common.get_login_creds"
    ],
    "target" : {
      "namespace" : "web_extension",
      "extension_id" : "dnifbcdaadaoifdojfdjhimhdaaoomio",
      "provider" : "chrome"
    }
  }
]

Known limitation: In the current implementation of WebExtensions of browsers, the extension_id is susceptible to change. On Chrome, this id is unique once submitted to the store, on Safari it seems to change between sessions... The fact that this id is not consistent will create issues when it comes to having multiple environments (prod, QA, dev...).

agl commented 2 years ago

This was discussed on the call of 2022-09-07. There weren't any firm objections, and I think we understand the request, but it seems that the WebExtensions group probably has a lot more pertinent knowledge.

Speaking for myself: I'm not aware if there is existing precedent for an assetlinks.json-style of authorisation for extensions or, if there is, how well it has worked out. If this is all pretty standard for extensions then it might be doable, but I'm not sure if we, in WebAuthn, are placed to do it.

agl commented 2 years ago

From the meeting of 2022-09-12: the WG decided to close this issue, effectively punting it to Web Extensions, although if new information comes up we would still ponder it.

arianvp commented 1 year ago

I would like this to be re-opened or at least linked to an issue in the Web Extensions group

1Password recently rolled out Passkey support and the UX is terrible. It inhibits the native Passkey flow with a small button on the top right that you need to click to get back to the native flow

image

I've been spending multiple hours this week with confused colleagues and friends who got locked out of their Passkeys because they didn't know they had to click the super small security-key-like icon to trigger the native passkey flow.

Browsers should deny overriding navigator.credentials.get from extensions because this UX is frankly unacceptable.

I don't want adoption of Passkeys to be hurt by bad UX from password managers.

irew commented 1 year ago

@arianvp this is not the same issue, this issue is about the RPID represented by web extensions, not about monkey patching the webauthn calls.

arianvp commented 1 year ago

Ah! should I open a new issue for this? Do we have an existing issue to allow extensions to hook into [[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors) without having to monkeypatch navigator.credentials.get ?

irew commented 1 year ago

I don't have an answer to that, but what I can say is that almost all password managers have to monkey patch WebAuthn in order to manage credentials. Some password managers are only based on browser extensions and have no other choice, at least as of today.

FlxMgdnz commented 1 year ago

I fully agree with Adrian here. Intercepting the native UI seems like a terrible idea.

I'm hoping that it's just a temporary solution until there's a way to configure passkey providers on the system level on all platforms (similar to iOS 17). Every .create() and .get() should invoke the native platform WebAuthn UI and only the way the passkey is stored and synced changes.

dwaite commented 1 year ago

I fully agree with Adrian here. Intercepting the native UI seems like a terrible idea.

I'm hoping that it's just a temporary solution until there's a way to configure passkey providers on the system level on all platforms (similar to iOS 17). Every .create() and .get() should invoke the native platform WebAuthn UI and only the way the passkey is stored and synced changes.

There are complex user-expectation and market challenges here.

I would personally recommend further discussion to be on a more-related issue, preferably not one which is closed.

This issue dealt with use of WebAuthn to enable functionality within a web extension, which do not have a stable origin (and thus a stable RPID) across web extension implementations in various browsers. It does not deal with web extensions offering credential functionality to web applications via patching or other API.

Proposal of new web extension API, such as a way to offer credentials to the browser/platform UX without page modifications, would likely need to be within the WebExtensions CG - I believe WebAuthn WG is currently only chartered for web apps.

arianvp commented 1 year ago

Sorry for accidentally hijacking an old issue. I opened a new issue to discuss designs: https://github.com/w3c/webauthn/issues/1976

irew commented 9 months ago

FYI: https://github.com/w3c/webextensions/issues/238#issuecomment-1875257521