Make Login Passkeys Identifiably Distinct from 2FA Passkeys on End Device

This one’s a bit confusing but I’ll try my best to explain the issue.

Let’s say I’m trying to save a passkey to my iCloud Keychain to login to Bitwarden with. iCloud Keychain is PRF-capable, so naturally I want to set it as a Login Passkey with Encryption to make it easy to login to the web vault.

The Login Passkeys aren’t currently supported on the iOS client. So, I have to login with the Master Password and 2FA. However, when I attempt to login this way, the passkey fails because the Login Passkey isn’t included as part of the FIDO2 2FA option. I have to fall back and use TOTP.

Well, when I try to add a second iCloud Passkey as a 2FA Passkey, iOS overwrites the PRF Passkey. iOS is seeing both the Login Passkeys and the 2FA Passkeys as the same passkey for the same account, same website, and same system, trying to be added twice, and overwrites it with the most recently added one. Thus, while Master Password + FIDO2 now works, Login with Passkey stops working.

I’ve tried workarounds such as adding one, moving it to trash, adding the other, and recovering the first one, but iOS still treats them as duplicates and they both become duplicate entries of the same passkey, and only 2FA or only PRF Login works.

I’m not sure what change can be made, but something should be changed so that they are treated as distinct passkeys, so that a PRF Login Passkey and a 2FA FIDO2 Passkey can coexist on the same device, and that each will work correctly when logging in.

That way, when logging in on the Web Vault on my iPad, I can skip past the master password and use my PRF Passkey, and whenever I need to re-login to my iOS client, I can use Master Password + Passkey rather than falling back on TOTP.

Does this make sense?

And I’m not sure, if this would be a change, Bitwarden could even make - but (in your case) iCloud would have to make it, e.g. by making a distinction between different credentials and/or allowing to save both types in one entry…

Possible workaround: If you made two entries, like 1) “Bitwarden (contains login-passkey)” and 2) “Bitwarden (contains 2FA-passkey)”, you should be able to store each passkey in one of those two entries separately, without overwriting.

(BTW, the same workaround could in general be done for the Bitwarden vault – a relevant feature request to that would be: Allow storing multiple passkeys on one vault item → initially I was sceptical with that feature request, but especially being able to store one discoverable credential (“passkey”) and one non-discoverable credential (typically for 2FA only), would be a use-case for being able to store more than one “passkey” in one vault item…)

I actually did do that as part of that thing I mentioned where I made one, deleted, made the second, recovered the first. They actually did have separate names, one was Bitwarden (PRF Key) and the other was Bitwarden (2FA Key). But that got… weird. When I restored the PRF one from the trash, it took on the 2FA one’s name, so they both were called 2FA Key. After testing them, and finding them both to only work on the 2fa screen, I deleted them… and then in the trash, they both suddenly took on the PRF Key name.

iOS still treated them like duplicate entries, meaning it uses a different identifier I can’t change in order to differentiate passkeys, and in a very glitchy way they were switching between the two names as I moved them in and out of the trash.

Ah. I suspected it, but wasn’t sure if that would mean you also tried more than one entry.

Hm, a few days ago I read this comments here: “No Passkeys found for this application” on AWS using the Bitwarden extension · Issue #14139 · bitwarden/clients · GitHub The point of it seems to be: iOS seems to “process” all FIDO2 credentials as discoverable credentials (if I understood that point correctly). Meaning: the BW-2FA-“passkey” and the BW-login-passkey probably both do get stored as discoverable credentials on iOS.

Maybe that they both share the same domain (bound to BW) also adds up to the mix up?

… Otherwise, I would say, where is the difference to other passkeys that get stored in another vault item?

Still, I’m not sure it is something BW could influence / change and might be more on IOS’s side… I’m not enough in the technical details to say anything useful to that now…

I have multiple passkeys for Google, but they’re for different accounts. They seem to work fine, and the correct passkey always gets discovered for the account I’m logging into.

Maybe Bitwarden could tack on “-2fakey” and “-prfkey” or “.2fakey” and “.prfkey” to the end of the “account” field?

Which “account” field? – I don’t think passkeys have an “account field”. :thinking:

But if it could be something, BW could change, maybe @Micah_Edelblut can say something to that.

Otherwise, you could also try to make a bug report - but it should be well reproducible (as they will try to reproduce it) and you’d have to “convince” them, it’s not an issue on Apple’s side. :wink:

Whenever I create a passkey on iOS, it’ll autofill the “User Name” field and the “Website” field in the Password app. I can’t change either of these. I was thinking that maybe tacking it on to the “User Name” would work?

That’s assuming there’s no other hidden identifiers that could be changed on Bitwarden’s backend during passkey creation… I don’t know much about the implementation of passkeys server-side.

For example, having [email protected] and [email protected]

I think it must at least be also on Apple’s side… – I just remembered, that I have absolutely no problem with having a BW-login-passkey and a BW-2FA-passkey both on my YubiKeys 5. (both things can be used without any problem)

Now, you can argue, they are stored there differently on that piece of hardware… but that only would enforce the argument, that the way they’re stored influences the result. :sweat_smile: Something must be different on iOS, so that it doesn’t work, other than with a YubiKey 5…

How does Android handle them? :eyes:

I don’t have an android device to test

Also I just had a thought… is the 2fa passkey on your yubikey being stored as challenge-response or some other non-passkey credential? :eyes:

Or are both the 2fa and login passkeys being stored on the yubikey as actual passkeys?

I have several accounts where I set up 2fa with my yubikey, and it doesn’t show up as a passkey in Yubico Authenticator, yet on my iPad I was able to set it up as a passkey in iCloud Keychain.

Although, I think that there may be an option server-side to make it hidden on yubikeys… my Google passkey for example doesn’t show up in YubiCo Authenticator.

I also know websites can determine if non-passkeys can prompt for PINs, but I’m fairly sure passkey credentials will always prompt for PIN.

If you’re prompted for a PIN when you use master password + yubikey, then a bitwarden dev would have to answer this question I think, they’ll know how Bitwarden has it configured.

No, I think it is safe to say that Bitwarden’s FIDO2-2FA-“passkey” can’t be stored as a “Challenge-Response” on the YubiKey.

Well, I can remember some discussions here in the forum (though I won’t search for the posts now :yawning_face:) if Bitwarden’s FIDO2-2FA-“passkey” is indeed a passkey (= FIDO2 discoverable credential) or strictly spoken not a passkey but only a “FIDO2 non-discoverable credential”. I’m not sure if I remember it correctly now, but I think the “result” was, that it can be stored as either, depending on the location where it get’s stored. (PS: … or I’m wrong and Bitwarden’s FIDO2-2FA-“passkey” gets always stored as the non-discoverable credential it is…)

As only the BW-login-passkeys get listed in the “passkeys” list on the YubiKey (via the Yubico Authenticator App, which can list all passkeys → BTW, a hint, that passkeys are “discoverable”)… but Bitwarden’s FIDO2-2FA-“passkeys” don’t get listed in that passkeys list in the Yubico Authenticator app, I’m pretty sure, that on the passkey YubiKey, the BW-FIDO2-2FA-“passkeys” get stored as “FIDO2 non-discoverable credentials”.

Here some things come together then, it seems:

  • as just described, your 2FA-credentials get then stored as “non-discoverable FIDO2 credentials” on the YubiKey (–> you don’t “see” them (or rather: the YubiKey can’t show them) → they are non-discoverable)

  • but as in the GitHub comment I linked previously written: it seems iOS treats every FIDO2 credential as a discoverable credential = as passkeys (= even then, when they are non-discoverable credentials, i.e. in a strict sense not a passkey) → that would explain, why you see the 2FA-credentials as “passkeys” in iOS

I could be wrong on all counts tho, this is just what I think from observing its behavior.

As far as I know, I would agree…

But I don’t think a PIN plays a role in your issue here - and it’s maybe not that easy solution, as if Bitwarden only would have to switch a setting here for it to work… :thinking:

I didn’t mention the pin as a configuration to change, but rather mentioned it as part of my behavioral observations of yubikeys with regard to identifying what type a given saved credential is.

I think I’m just trying to get a grasp on what is going on in the interactions between bitwarden, various authenticators, and various platforms.

I want to understand how all this is working. Is this duplicate thing happening on Android as well? What allows the YubiKeys to differentiate different credentials for the same account on the same website if they’re both supposedly fido2 (and can it be verified that both are indeed fodo2 on the yubikey)? Is there something in there to be found that can be worked with in the iOS issue?

I’m trying to analyze everything but only have a keyhole to look through, and I’m thinking from the perspective of, trying to find workarounds.

Yubico has a good write-up on the difference between discoverable and non-discoverable credentials, which is what this boils down to.

Note that they state that only discoverable credentials can properly be referred to as Passkeys. Bitwarden doesn’t share this view.

As to the feature request, Bitwarden could differentiate between a discoverable credential (used for login) and non-discoverable ones (used for 2FA). We also have feature enhancements we are contemplating that would allow users more control over what their passkeys can be used for (2FA, login, unlock). This could alleviate the issue with an authenticator overwriting your login passkey when registering a 2FA passkey, or vice versa.

Not only Yubico sees it that way. The WebAuthn specs (and the FIDO Alliance) also share this view (and they are the ones, defining the standards here…).

Only discoverable credentials get called “passkeys” in the current W3C working draft Level 3:

Non-discoverable credentials on the other hand don’t get associated with the term “passkey” at all:

And from passkeys.dev (site from W3C and the FIDO Alliance):

(–> passkeys.dev - Terms)

I’m still not sure, why Bitwarden decided to not use the official definition of “passkeys” as a discoverable credential. :thinking:

[PS: By that I’m not criticizing any technical features, but only that the “labels” aren’t used as the standards define them…]

Anyway…

Those would be some improvements!

1 Like

I’m not sure, I can really answer or test this.

I do have an Android device - but as all passkeys for me only get stored in “Google” (in my Google account), I’m pretty sure by now, that my device doesn’t have a “hardware module”, where the passkeys could be stored “really” on the device itself.

Maybe I’ll try it anyway the next days (and see how my phone / Google handle it)…