WebAuthn credentials requires PIN even when user verification and discoverable credentials are "discouraged"
Categories
(Core :: DOM: Web Authentication, defect, P3)
Tracking
()
People
(Reporter: cleyfaye, Assigned: jschanck)
References
Details
Steps to reproduce:
UA of the browser displaying the issue: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0
- Go to webauthn.io
- in advanced settings, set both user verification and discoverable credentials to "discouraged"
- register with a FIDO2 token (YubiKey 5)
Actual results:
To register, a PIN is asked, and upon entering it a discoverable credential slot is used on the token.
Expected results:
With both "user verification" and "discoverable credentials" set to discouraged, a PIN should not have been asked, and no discoverable credentials should be stored on the token.
This expected result is supported by both the documentation and various other implementations.
Setting security.webauthn.ctap2
to false remove the PIN requirements, but does not seems like a future-proof solution. Disabling the FIDO2 interface on the token also seems to work as it fallback to FIDO2 U2F.
A similar issue was found in #1811866 but the current state of things does not match the resolution status.
Updated•1 year ago
|
Comment 1•1 year ago
|
||
The Bugbug bot thinks this bug should belong to the 'Core::DOM: Web Authentication' component, and is moving the bug to that component. Please correct in case you think the bot is wrong.
Assignee | ||
Comment 2•1 year ago
|
||
I'm not able to reproduce this with a YubiKey 5 NFC running firmware version 5.4.3. Can you run ykman info
and copy the "Device type" and "Firmware version" lines here?
Sure. It seems I have a different firmware version. I have a hard time finding details about different firmware versions, though.
Device type: YubiKey 5 NFC
Firmware version: 5.2.4
Form factor: Keychain (USB-A)
Enabled USB interfaces: OTP, FIDO, CCID
NFC transport is disabled.
Applications USB NFC
FIDO2 Enabled Disabled
OTP Enabled Disabled
FIDO U2F Enabled Disabled
OATH Enabled Disabled
YubiHSM Auth Not available Not available
OpenPGP Enabled Disabled
PIV Enabled Disabled
Assignee | ||
Comment 4•1 year ago
|
||
Will, any idea what might be going on here? Does YK5 firmware 5.2.4 imply a max supported version of FIDO_2_0 instead of FIDO_2_1_PRE?
Comment 5•1 year ago
|
||
Not sure making an un-requested discoverable credential is a new one for me.
That should be a FIDO_2_1_PRE device (it supports credprotect & credential management). I'll try and see if I can get ahold of a 5.2.4 device to test.
@clayfaye, can you test with this site and see how it behaves?
https://demo.yubico.com/webauthn-technical/registration
This site is hard-coded to make a non-discoverable, non-uv credential.
When registering, it did ask me for a PIN, then to touch the device (same behavior I see on webauthn.io), then succeeded.
However, it did not ask for a PIN to "authenticate", and listing the stored credentials on the key did not show a new one.
It seems I mixed up different tests (obviously I didn't initially come across this issue on webauthn.io, it was just a convenient way to reproduce the issue), and while a PIN is asked, it actually does not store a credentials on the key in that case. Sorry about that.
It does, however, always ask for a PIN when registering, which I feel is still not the expected behavior in this case. I may be biased because it does not ask for a PIN in other browsers, I only noticed this behavior afterward in Firefox. However this is based on my limited experience with these keys, and the issue may be with other's implementations.
If it is expected to ask a PIN at registration in this scenario, then I'm sorry for the noise.
I'm not sure dumping the data from the demo would still be relevant, but I'll just post everything here anyway in case the PIN situation is not as expected (I do know that there is nothing sensitive in there) :
navigator.credentials.create()
argument:
{
"publicKey": {
"attestation": "direct",
"authenticatorSelection": {
"requireResidentKey": false,
"residentKey": "discouraged",
"userVerification": "discouraged"
},
"challenge": "6Toq+v9Zu1wYrkkTtfDgQXVmvhe2w48XgoVSX+jJwX0=",
"excludeCredentials": [],
"pubKeyCredParams": [
{
"alg": -7,
"type": "public-key"
},
{
"alg": -257,
"type": "public-key"
}
],
"rp": {
"id": "demo.yubico.com",
"name": "Yubico Demo"
},
"timeout": 90000,
"user": {
"displayName": "Yubico demo user",
"id": "m71W1UXHKeI3mveGf/MJjmMcVmQIG8RGvcEQUssaY/Q=",
"name": "Yubico demo user"
}
}
}
navigator.credentials.create()
response:
{
"id": "4h5Ku-j22zKLrEPDCs2CmL5DQDHMAyr6dvUK55LoJEPvhBmRYdKge1jDNJ6IJRhYkXbo774-YCqqDmpQY7aMUg",
"response": {
"attestationObject": "o2NmbXRmcGFja2VkZ2F0dFN0bXSjY2FsZyZjc2lnWEcwRQIhAPAs+Vu4hkN13sC1T6HBDU4DAvDCqUBT9Qb8ABtle6XSAiBnaezaM9S8OTuaNK8llqD11iipTuO/ThOATAlm7TsYmGN4NWOBWQLCMIICvjCCAaagAwIBAgIEXdBO4TANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowbzELMAkGA1UEBhMCU0UxEjAQBgNVBAoMCVl1YmljbyBBQjEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlvbjEoMCYGA1UEAwwfWXViaWNvIFUyRiBFRSBTZXJpYWwgMTU3MzkzMjc2OTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCNp4As+URnWqbTRh760QYDNrHHqUpiB4+d9HPWBoTtnMSupMoY1ncNIDYET1l4UFOzm0Q67LR7I3Zo/Av1cgNSjbDBqMCIGCSsGAQQBgsQKAgQVMS4zLjYuMS40LjEuNDE0ODIuMS43MBMGCysGAQQBguUcAgEBBAQDAgQwMCEGCysGAQQBguUcAQEEBBIEEC/AV5+BE0fqsRa7Wo25ICowDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAh8odJU4o9FIUYSm3h1UhrTGfnukczFJd3ojEJnxzZBnDBye7VfzVFJ05VQzu859HI3mRxK5FH4HLo6LnVrKrKh7cPEhECrQgEgbtjIwD+AAXQkAAZT1eyng572o82o/6Ua9e0/N+BktXV3TwzPGgMQaWGgql41gyiRc+8YBBbWF+ozozvRT2h+qexpd7YwPVk6FRiLhNyiqhl9qpnraHtrcQyEl++5PMnCUSygNyKTzS9DH7d8G+qTFZV23bdecAyjS2EcfztFLSs0Au6+jLLvt9R0pjGW28kObE8F9BBkJtLKZtPaw3W/LyZXOxs3PK+iENM5K3UtbbKPPi2a/AYWhhdXRoRGF0YVjExGzvgq0bVGR3WR0Aiwh1nsPm0uy085R0v+ppaZJdA7dFAAAAAS/AV5+BE0fqsRa7Wo25ICoAQOIeSrvo9tsyi6xDwwrNgpi+Q0AxzAMq+nb1CueS6CRD74QZkWHSoHtYwzSeiCUYWJF26O++PmAqqg5qUGO2jFKlAQIDJiABIVggSL4JXRZVWAMWQFS3yc5teAysEta8V79BGHQyEM8S3voiWCDK2SN9Us39eYWH+nXvyfrVAUaPejAc6A2o0RJsWAd0EQ==",
"clientDataJSON": "eyJjaGFsbGVuZ2UiOiI2VG9xLXY5WnUxd1lya2tUdGZEZ1FYVm12aGUydzQ4WGdvVlNYLWpKd1gwIiwib3JpZ2luIjoiaHR0cHM6Ly9kZW1vLnl1Ymljby5jb20iLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0="
},
"clientExtensionResults": {}
}
parsed clientDataJSON
response:
{
"challenge": "6Toq-v9Zu1wYrkkTtfDgQXVmvhe2w48XgoVSX-jJwX0",
"origin": "https://demo.yubico.com",
"type": "webauthn.create"
}
Response from the Relying Party:
{
"success": true,
"attestationObject": {
"attStmt": {
"alg": -7,
"sig": "MEUCIQDwLPlbuIZDdd7AtU+hwQ1OAwLwwqlAU/UG/AAbZXul0gIgZ2ns2jPUvDk7mjSvJZag9dYoqU7jv04TgEwJZu07GJg=",
"x5c": [
"MIICvjCCAaagAwIBAgIEXdBO4TANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowbzELMAkGA1UEBhMCU0UxEjAQBgNVBAoMCVl1YmljbyBBQjEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlvbjEoMCYGA1UEAwwfWXViaWNvIFUyRiBFRSBTZXJpYWwgMTU3MzkzMjc2OTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCNp4As+URnWqbTRh760QYDNrHHqUpiB4+d9HPWBoTtnMSupMoY1ncNIDYET1l4UFOzm0Q67LR7I3Zo/Av1cgNSjbDBqMCIGCSsGAQQBgsQKAgQVMS4zLjYuMS40LjEuNDE0ODIuMS43MBMGCysGAQQBguUcAgEBBAQDAgQwMCEGCysGAQQBguUcAQEEBBIEEC/AV5+BE0fqsRa7Wo25ICowDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAh8odJU4o9FIUYSm3h1UhrTGfnukczFJd3ojEJnxzZBnDBye7VfzVFJ05VQzu859HI3mRxK5FH4HLo6LnVrKrKh7cPEhECrQgEgbtjIwD+AAXQkAAZT1eyng572o82o/6Ua9e0/N+BktXV3TwzPGgMQaWGgql41gyiRc+8YBBbWF+ozozvRT2h+qexpd7YwPVk6FRiLhNyiqhl9qpnraHtrcQyEl++5PMnCUSygNyKTzS9DH7d8G+qTFZV23bdecAyjS2EcfztFLSs0Au6+jLLvt9R0pjGW28kObE8F9BBkJtLKZtPaw3W/LyZXOxs3PK+iENM5K3UtbbKPPi2a/AYQ=="
]
},
"authData": {
"credentialData": {
"aaguid": "L8BXn4ETR+qxFrtajbkgKg==",
"credentialId": "4h5Ku+j22zKLrEPDCs2CmL5DQDHMAyr6dvUK55LoJEPvhBmRYdKge1jDNJ6IJRhYkXbo774+YCqqDmpQY7aMUg==",
"publicKey": {
"1": 2,
"3": -7,
"-1": 1,
"-2": "SL4JXRZVWAMWQFS3yc5teAysEta8V79BGHQyEM8S3vo=",
"-3": "ytkjfVLN/XmFh/p178n61QFGj3owHOgNqNESbFgHdBE="
}
},
"flags": {
"AT": true,
"ED": false,
"UP": true,
"UV": true,
"value": 69
},
"rpIdHash": "xGzvgq0bVGR3WR0Aiwh1nsPm0uy085R0v+ppaZJdA7c=",
"signatureCounter": 1
},
"fmt": "packed"
},
"clientData": "eyJjaGFsbGVuZ2UiOiI2VG9xLXY5WnUxd1lya2tUdGZEZ1FYVm12aGUydzQ4WGdvVlNYLWpKd1gwIiwib3JpZ2luIjoiaHR0cHM6Ly9kZW1vLnl1Ymljby5jb20iLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0=",
"device": {
"mds": {
"certifications": [
"FIDO_CERTIFIED_L1"
]
},
"names": [
"YubiKey 5 NFC",
"YubiKey 5C NFC"
],
"type": "yk5nfc-cnfc"
}
}
Followed by an X509 certificate matching my key's serial number.
Comment 7•1 year ago
|
||
Thanks @clayfaye - generally speaking the output from webauthn debugging is not terribly sensitive, especially when used with sites designed to test FIDO2 authenticators.
It's good that it's not making discoverable credentials, because that had me positively stumped.
I can confirm the bug behavior w/ a firmware 5.4.3 YubiKey on the FF118 beta.
I had a look at authenticator.rs, and I think this issue is with https://github.com/mozilla/authenticator-rs/blob/915bcbc289101a50beb093c6ac9d9dc3d6a15c12/src/ctap2/commands/make_credentials.rs#L385C71-L385C71
It should be possible to create a non-UV credential even if a PIN has been set on the authenticator:
Otherwise, implying the authenticator is not presently protected by some form of user verification, or the Relying Party wants to create a non-discoverable credential and not require user verification (e.g., by setting options.authenticatorSelection.userVerification to "discouraged" in the WebAuthn API), the platform invokes the authenticatorMakeCredential operation using the marshalled input parameters along with the "uv" option key set to false and terminate these steps.
https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-errata-20220621.html#sctn-makeCred-platf-actions
!always_uv && (!device_protected || make_cred_uv_not_required)
should probably just be !always_uv && make_cred_uv_not_required
Now I have to go back and figure out why my testing suite didn't detect this as an issue, because I didn't notice it as a problem while testing the initial CTAP2 support.
Assignee | ||
Comment 8•1 year ago
|
||
OK, we can change this, but the spec needs to be updated too.
"Otherwise" in the section Will quoted is the "else" branch for
If the authenticator is protected by some form of user verification, or the Relying Party prefers enforcing user verification (e.g., by setting options.authenticatorSelection.userVerification to "required", or "preferred" in the WebAuthn API):
The device is "protected by some form of user verification", so we followed the "if" side of the branch.
Assignee | ||
Comment 9•1 year ago
|
||
Actually, I'm still confused. The makeCredUvNotRqd
option says
present and set to false, or absent: the authenticator requires some form of user verification for creating non-discoverable credentials, regardless of the parameters the platform supplies for the authenticatorMakeCredential command.
My YK5 running the 5.4.3 firmware does not return the makeCredUvNotRqd
option. So I think our behavior is correct.
Comment 10•1 year ago
|
||
I've requested some clarification from our spec folks, but I think you may be right.
I've discovered that the behavior on Chrome appears to be a result of Chrome pre-emptively falling back to U2F - if you disable U2F on the Yubikey, Firefox 118 and Chrome behave the same way.
Comment 11•1 year ago
|
||
@jschanck - You are technically correct. The CTAP2 spec does require UV for new registrations if a PIN is set on the authenticator - regardless of whether a credential is discoverable or not, or whether the RP sets UV=discouraged. I'm still trying to get some clarification on the spec wording.
In CTAP2.1-pre, makeCredUvNotRqd was added as a property that an authenticator could set to signal to platforms that it would allow new registrations without UV, if the RP set UV=discouraged, even if a PIN was already set on the authenticator. Neither the 5.2.4 keys nor the 5.4.3 support makeCredUvNotRqd.
I think the reason why @cleyfaye (and I) saw this as a bug is because other platforms (Chrome on Mac/Linux) will see this situation and silently downgrade the communication with the authenticator to CTAP1 (U2F) - so this behavior is unexpected, but not because the Firefox implementation of the CTAP2 spec is incorrect.
You can cause this behavior on Chrome by disabling the U2F Protocol on a YubiKey and then re-trying the test. You'll get the PIN prompt just like FireFox 118.
Description
•