I tried to add a FIDO2 key to Google's passkey page and failed already, so it doesn't seem entirely compatible out of the box.
I tried to add a FIDO2 key to Google's passkey page and failed already, so it doesn't seem entirely compatible out of the box.
I am surprised that the FIDO2 key doesn't work on Google, but it probably just means that there is a bug somewhere in the implementation.
FIDO marketing materials talk about passkeys in the same way you do, a resident key (now called discoverable credentials). Some other materials say that passkey with no other qualifier is a multi-device passkey, meaning it's backed up by a sync fabric. (e.g. the short version here https://passkeys.dev/docs/reference/terms/#passkey). Others, like Google did in their blogpost last week and the long version of that link, say that a passkey is a multi-device passkey that also has user verification (so it can be used for passwordless and not just 2FA/2SV).
Most hardware tokens don't support discoverable credentials.
The default U2F/FIDO2 model was to use a single secret on the token, and deterministically generate a public-private keypair as required. At registration the token provided some opaque bytes to the website, and the website must supply those bytes back to the token when trying to authenticate.
Registration:
1. Token generates random seed
2. Token calculates public/private keypair by combining seed with global secret
3. Token signs registration request using private key
4. Token returns seed, public key, and registration request to server
5. Server stores seed and public key in user's database entry
Authentication:
1. User provides username
2. Server looks up user's seed and public key in user database
3. Server provides seed to token
4. Token calculates public/private keypair by combining seed with global secret
5. Token signs authentication request using private key
6. Token returns signed authentication request to server
7. Server validates authentication request against stored public key, and user is now authenticated
The biggest benefit of this is that the token is quite trivial to create as there is no need to store a per-website secret on it. One secret can be securely used to authenticate with an infinite number of websites without any security or privacy risks.
Passkeys use resident keys. This basically means that the seed is not stored on the server, but on the token. The biggest benefit of this is that you can also get rid of the username in the authentication process.
Registration:
1. Token generates public/private keypair
2. Token signs registration request (which includes unique token identifier) using private key
3. Token stores private key, together with website URL
4. Token returns public key, and registration request to server
5. Server stores public key and unique token identifier in user's database entry
Authentication:
1. Token looks up public/private keypair using website URL
2. Token signs authentication request
3. Token returns authentication request and unique token identifier to server
4. Server looks up user's entry in user database by unique token identifier
5. Server validates authentication request against stored public key, and user is now authenticated
And before you ask: no, I have no idea how this is supposed to work if you have multiple accounts on the same website either.
If you've got multiple accounts on a site, each with different credentials, you have to have some way to select which of your accounts you want to use.
Specifying the UI that clients should use for letting you specify that is entirely a client issue, so seems out of scope for the Passkeys specification.