Comments (11)
So here is a reply from Google team:
RP IDs are defined to be a domain name, but extensions don't have a domain name. In order to avoid collisions with domain names, different identifier spaces are distinguished by representing them as URLs. See this note in the spec: https://www.w3.org/TR/webauthn-2/#ref-for-webauthn-client%E2%91%A4:~:text=Other%20specifications%20mimicking%20the%20WebAuthn%20API%20to%20enable%20WebAuthn
Chrome extensions are not intended to specify an RP ID in the WebAuthn call at all although it does happen to work if you specify the extension ID.
from simplewebauthn.
The debugger is a rich idea you had 👍 hopes we make webauthn a great standard everywhere 😄
from simplewebauthn.
After bootstrapping a new extension using Mozilla's "baby's first extension" tutorial I tried to find out if it's possible for an extension to discover its internal UUID. It seems it is indeed possible to get the current UUID via the runtime.getURL()
API:
const imgURL = browser.runtime.getURL('manifest.json');
const idRegEx = /^moz-extension:\/\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/;
console.log(`extension UUID: ${idRegEx.exec(imgURL)}`);
Which matches with the UUID that's visible from the extensions page:
Can you use this technique to get a given instance's UUID string, which you can then pass in as rpID
for options or expectedRPID
for verification?
Edit: Have you figured out what the RP ID is that comes out of an attestation that takes place in a browser extension?
from simplewebauthn.
So we've made some tests and we found out that the RP ID is similar to the origin. See this assertion in the SWA debugger here.
If you take the rpID hash it's "e71bb73760cf488dcef0732f92017e7f05f2d92b99dc76b7b604a517ebb60793"
Now trying to found this hash from the uuid:
> a = crypto.createHash('SHA256').update(Buffer.from('gnmebdeegofghllmmlngmdmoghkebpmf', 'ascii')).digest(); console.log(a.toString('hex'));
372c27c61b49497b4dd746f02ce598d4d07efe605858c05d578aae148bc3ed83
> a = crypto.createHash('SHA256').update(Buffer.from('chrome-extension://gnmebdeegofghllmmlngmdmoghkebpmf', 'ascii')).digest(); console.log(a.toString('hex'));
e71bb73760cf488dcef0732f92017e7f05f2d92b99dc76b7b604a517ebb60793
So in this example the RPID === origin. But what's interesting is that the parameter passed to webauthn.create was only "gnmebdeegofghllmmlngmdmoghkebpmf"
. So that means something changed it on it's way.
And here is a interesting PR on webauthn project: w3c/webauthn#1033 that may explain this behavior.
We also tried to pass different things to the webauthn.create but ended up with DOMException: Public-key credentials are only available to HTTPS origin or HTTP origins that fall under 'localhost'.
.
Concerning the fact that we can get the uuid with runtime.getURL()
it's known. But the issue is that the server is not aware of it as we put our expectedOrigin/RPID in our configuration.
I hope this helps but to be honest there is a big lack of documentation around webauthn and extensions 😞
from simplewebauthn.
I suspect you're suffering from nuances of the CTAP2 protocol, the part of WebAuthn that dictates how the authenticator generates a response for whatever options the browser gives it.
It seems for Chrome specifically you need to pass in the full extension URI for expectedRPID
, not just the extension's ID...this isn't the case with Firefox? Is there the added twist that the rpIdHash
in Firefox extensions is generated from just the ID as expected?
I feel like this isn't related to WebAuthn extensions...it might save you some headache to table that investigation for now. I'm going to look at the CTAP2 part of the spec a bit closer and see if anything in there explains this. Maybe it's a browser implementation issue 🤷♂️
from simplewebauthn.
I found this part in the spec:
The RP ID is originally received from the client when the credential is created, and again when an assertion is generated. However, it differs from other client data in some important ways. First, unlike the client data, the RP ID of a credential does not change between operations but instead remains the same for the lifetime of that credential. Secondly, it is validated by the authenticator during the authenticatorGetAssertion operation, by verifying that the RP ID that the requested credential is scoped to exactly matches the RP ID supplied by the client.
Authenticators perform the following steps to generate an authenticator data structure:
- Hash RP ID using SHA-256 to generate the rpIdHash.
Now I'm suspecting Chrome itself will end up being the culprit, as it's responsible for passing along your rpID
in the options you provide to its navigator.credential
APIs. If it's tacking on chrome-extension://
to the front of the value you provided then that doesn't seem compliant with the spec.
It's worth noting you're in a bit of uncharted waters with all of this because I don't think the spec particularly accounts for the use of this API in browser extensions.
from simplewebauthn.
So I made a series of tests.
For Chrome:
-
Don't work when a protocol different than
https
is specified. -
Works only with rpID set with the ID of extension (like
nhnjjlokanokjhheekkcgoiblhljealo
) and then in the attestation response it was modified (by the browser? 🤷♂️ ) tochrome-extension://nhnjjlokanokjhheekkcgoiblhljealo
.
See example here.
For Firefox:
-
Don't work when a protocol different than
https
is specified. -
When setting the rpID to the UUID, the ui is triggered but I was unable to validate my Yubikey nothing was happening until timeout.
So I don't know if it works at all on Firefox or if I missed something.
from simplewebauthn.
I think webextensions fits in this part 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].
https://www.w3.org/TR/webauthn/#note-pkcredscope
from simplewebauthn.
Hello again,
I have opened a discussion with Mozilla: https://bugzilla.mozilla.org/show_bug.cgi?id=1693562
There are interesting elements to discuss.
Also I created a test extension: https://github.com/Mikescops/webauthn-extension-playground
from simplewebauthn.
@Mikescops Thank you for the update! Seeing WebAuthn in action in a browser extension is pretty exciting for me, even with Firefox giving you issues (and I totally approve of how you linked to the SimpleWebAuthn debugger 😛). I'll be following that Mozilla bugzilla entry you linked, here's hoping for a speedy resolution 🤞
from simplewebauthn.
I'm going to go ahead and close this as there's not much in the way of action items for me. I'll take another look at this in the morning and maybe migrate it to a discussion so we don't lose the links you provided earlier to the Closed Issues tab.
from simplewebauthn.
Related Issues (20)
- Treat all custom string challenges as UTF-8 strings
- Uint8Array --> String --> Uint8Array Conversion from isoUint8Array helper doesn't work HOT 3
- Cannot find module 'cbor-x/index-no-eval' or its corresponding type declarations. HOT 9
- ignore `node:crypto` import with webpack in `@simplewebauthn/server` HOT 8
- Update minimum Node support to v20+ HOT 3
- library reports lack of support to webauthn in mobile chrome but webauthn seems to work if using reference site HOT 8
- Using Android devices without non-Google Password managers fail to authenticate HOT 11
- Change signature of `decodeClientDataJSON` to accept `Base64URLString` as paramater HOT 2
- Improve ergonomics of `excludeCredentials` and `allowCredentials` HOT 3
- Remove footgun related to random user IDs HOT 16
- Update `getWebCrypto()` for Node 20 HOT 2
- cross-platform authenticator usage on android 14 HOT 1
- Default `userDisplayName` to empty string when not specified HOT 1
- Handle undefined `PublicKeyCredential` in `browserSupportsWebAuthnAutofill` helper HOT 1
- Discrepancy between example code and docs HOT 4
- get public key as string
- Make rpID required when generating authentication options HOT 1
- Clean up some docstrings in @simplewebauthn/server
- Rename `AuthenticatorDevice` type and usage
- Parsing the attestation data explicitly HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from simplewebauthn.