No passkeys found

I am using the bitwarden chrome extension on ubuntu linux. I am able to register a passkey in bitwarden for sites like passkeys.io without any problems. Authentication with this saved passkey also works.

What I am working on now is setting up passkeys integration for my own website on my workstation. This is working if I try to register and use a passkey on an iphone client that is not using bitwarden. So it seems my website is working with passkeys. However, if I try to use my desktop running chrome and the bitwarden extension to manage the passkeys, I get an error. The registration part works fine, but as soon as I try to authenticate, I get this error: “No passkeys found for this application”. What steps can I use to troubleshoot this? If it is working on iphone, shouldn’t it also work with bitwarden?

BTW, for passkey authentication and registration with my app, I am using a local keycloak server over https that is signed by a custom CA, if it matters.

No-passkeys-found

ok, I just updated to the latest version of bitwarden chrome extension. I still get this error.

The other weird thing I’ll point out, is that the extension icon does change to put a little “1” in front before I try the authentication. This indicates that the extension should be able to find something that matches, right?
Screenshot from 2024-07-30 12-27-09

Yes, you can click on the extension icon to view the matching vault item.

Right, I can click on the extension icon and see the details of the matching site. However, if I click “sign in with passkey” in my application, the bitwarden extension still pops up and says " No passkeys found for this application". I’ve tried editing the item within bitwarden to change the match detection to something like “base domain” or “host”, but I always get the same error from bitwarden.

When I use the iphone as an authenticator for this app, it works fine. Maybe iphone is just more polished in they way it does matching?

  • When you open the matching vault item, does it actually contain a passkey?

  • If you go to Settings > Notifications > Excluded Domains, does the problematic website URL appear in this list?

yes, there is a passkey shown there. I checked the excluded domains and the list is empty.

It seems that the passkey configuration on your server is not completely correct, then. Are you using passwordless.dev for this?

I am not using passwordless.dev for this. I am using a keycloak server running locally. Check out https://www.keycloak.org/

It could very well be I have something configured on my side that is not correct, I’m just not sure what it is. It just seems that iphone as an authenticator is much more forgiving in this regard. I’d really like to get the bitwarden part working though. I’d like to make my website as compatible as possible with different authenticators.

So it seems we have this situation where bitwarden finds a matching site to at least update its icon, but does not have a match when I actually push the “sign in with passkey” button. I’d like to know more about what part matches, but doesn’t match - if you know what I mean. What data is bitwarden getting from my pressing the “sign in with passkey” button that it can’t find a match for?

I don’t have an answer for your questions, but perhaps you can consider starting from scratch using the passwordless.dev toolkit, which is advertised as “the easiest way to build passkeys”, and is free for sites with up to 10,000 users.

ok, I got it to work!

I figured my question was specific enough that why not just look at the source code? So I did. And to me, it just points out a key difference between bitwarden and Apple. Apple is indeed more lenient.

For the code inclined, this is the code snippet where the check is failing:

libs/common/src/platform/services/fido2/fido2-authenticator.service.ts

  private async findCredentialsByRp(rpId: string): Promise<CipherView[]> {
    const ciphers = await this.cipherService.getAllDecrypted();
    return ciphers.filter(
      (cipher) =>
        !cipher.isDeleted &&
        cipher.type === CipherType.Login &&
        cipher.login.hasFido2Credentials &&
        cipher.login.fido2Credentials[0].rpId === rpId &&
        cipher.login.fido2Credentials[0].discoverable,
    );
  }

I stepped through this in the debugger and found that all my credentials had the discoverable flag set to false. So bitwarden couldn’t find any stored credentials that match the rpId and are discoverable. Once I reconfigured keycloak to require discoverable credentials, I was able to reset the credential and re-register it within bitwarden and login now works.

So, before when I registered my credential in bitwarden, it was set as a non-discoverable credential. I couldn’t find anywhere in bitwarden where it told me that. I only discovered it stepping through the debugger. So bitwarden allows you to register a credential that it won’t be able to find.

It seems Apple gets around this usability problem and just treats the credential being registered as discoverable, no matter what setting I selected in keycloak. It sure makes the apple keychain easier to use in this case, but is it correct? Not sure.

It would be nice if this condition were easier to detect in bitwarden without using a debugger though.

1 Like

Hey, Anders here from the passwordless team at Bitwarden.
First of all - I’m happy you were able to resolve your problem.

I’ll just add some additional information to explain the difference in behaviours.

Apple always creates what is known as discoverable credentials. However, our implementation also supports the older version of fido2-credentials, which are known as non-discoverable or non-resident. For these credentials to be used, they require the RP (the app) to first identify the user and to send the intended credentialId in a allow-list - we then show only those credentials matching the ID’s given to us.

There are several technical reasons for that design, but one of the properties is that the RP must first identify the user before such credential can be used. Those credentials have historically been used as 2FA only, while discoverable credentials are designed to be used as the primary (and only) authentication method,

There are more details to it, but it’ll stop there.

For anyone reading this that are looking to start using passkeys - Use discoverable credentials and I also recommend checking out passwordless.dev to get up and running with passkeys in minutes.

1 Like

Thanks for the explanation, @andersaberg . This makes more sense now. How about adding something in the view item UI to indicate the passkey is discoverable or not? And maybe a tooltip to explain what that terminology means. Maybe:
discoverable=false “The website must supply the username to bitwarden during authentication”
discoverable=true “The website does not need to supply a username to bitwarden during authentication. Bitwarden will allow you to choose among multiple stored passkeys for this website”

I’m hoping that passkeys becomes more widely deployed. Extra troubleshooting hints like this would help ease the transition away from passwords.

So I just tried to register another user named Bob for the same website that uses passkeys only for authentication. Bitwarden says, “choose a login to save this passkey to”. There is only one login listed. If I examine closely, the username of the passkey I created earlier is shown, which is Alice. I’m not really sure why it needed to tell me that, but I did see the website name listed so I click “save passkey”. I get a popup warning that says “Overwrite passkey? …” This question seems puzzling to me. Why is it telling me this item already contains a passkey? Why would I want to overwrite Alice’s passkey with Bob’s? Bitwarden should have enough context to know I am attempting to register a passkey for a different username, right? Why can’t the default action just be to save a new passkey under Bob in this case?

So just playing along here, I click yes. Now when I go to authenticate in the app using bitwarden as the authenticator, I see bitwarden has stored the passkey under the username Alice. Yet, when I authenticate my application shows that Bob has logged in. So the default action in bitwarden for registering a 2nd username/passkey seems to guide the user into corrupting the first user, Alice.

Maybe I’m just used to how Apple handles this case. It just blindly stores a 2nd or 3rd login as necessary during registration. There is no need to overwrite the passkey for a different user.

Just for grins, I added a third user, Charlie to my application. I went through the normal registration process to give this user a passkey with bitwarden as the authenticator. This time, I look closer at the screen and there is a “+” at the very top of the window. Sure enough, if I click this it shows the correct username Charlie in the form. I click save and then bitwarden does save Charlie’s username and passkey correctly. I am able authenticate in my app and see 2 choices listed - Charlie and Alice. If I pick Charlie I am logged on correctly in my app as Charlie.

So it looks like bitwarden is working, but the UI could be better in this case. So in the case of registering a new username/passkey like Bob, would it be possible for the “save passkey” button on the initial screen to just create a new user Bob with his passkey? I guess I’m not seeing the use case where the user wants to override someone else.

1 Like

Your whole text here reads to me like it is necessary to explain something:

Passkeys, stored in the Bitwarden vault, are stored in a “vault item” of the “login” type. Only one passkey can be stored in one login-vault item.

The vault item must have the corresponding URI in it so that Bitwarden offers to store the passkey there…

And so passkeys don’t get stored to or “under” a “username”, but to a vault item (while the passkey itself in the service can be associated with a certain username).

I guess when you have only one login vault item with the corresponding URI in your vault and try to store another “username”/passkey, then of course Bitwarden tries at first to overwrite the “old” passkey, as a vault item can only store one passkey, as explained above. For every “username”/passkey you must have a separate vault item (as long as Bitwarden doesn’t allow to store multiple passkeys in one vault item).

Hope that clears at least something up? Or I missed the point completely… :sweat_smile:

The point I was trying to make is why is the default experience in bitwarden to replace anything in this case? Bitwarden should know I’m trying to register a new username with a new passkey, since Bob doesn’t match Alice. Besides, Alice already has a passkey. Instead, I would think it should just offer to create a new login-vault item, if I have the terminology correct. Both vault items have the same URL.

I could be missing something though. I’m rather new to bitwarden, but it feels like there is this underlying assumption that everyone using passkeys will always use it as an authentication option for an existing username/password vault item. So when you register a passkey bitwarden guides you down this path to match the passkey to some other vault item that matches this URL.

However, for my new website I’m using passkeys only for authentication - no passwords. So the model of matching vault items to a new passkey is breaking down for me.

Yeah, I got the point of that one as well.

It was a discussion from the beginning, why “only” one passkey per vault item in Bitwarden… but I guess “in the field”, most of the time it is enough for most users… ?! (can only speak for myself: in the beginning, I was irritated too, that “only” one passkey was possible for one vault item… but until now, I never needed more than one passkey… actually, I’m happy enough to be able to create a passkey at all for a given website)

And to use your terminology: maybe Bitwarden doesn’t expect you being Alice and Bob at the same time?! :wink:

(and that reminds me of the “terms of service/use” stating one Bitwarden account is for one user… honestly, if it was explicitly allowed to share your account, being able to only store one passkey per vault item would be much more of an issue, I guess)

When I first saw the this dialog, my first thought was, “well, that’s too bad. I guess bitwarden only supports one login with a passkey for a website”

bitwarden-overwrite-passkey

But it turns out bitwarden is able to handle multiple logins with passkeys for the same URL. It’s just that the UI is unnecessarily confusing in this case.

1 Like