It sounds like the user id property is just a replacement for a username, while the keypair replaces the password. In effect, the authenticator stores both the username and password constructs, and there is a formal ceremony for exchanging it without user intervention.
It would seem pretty similar to a formal process by which a site asks me to unlock my Bitwarden, and it simply extracts the username and password out of the application by matching the URI. I’m guessing the “metadata” must include a URI or something similar to identify the site…
What if there are multiple accounts for the same site?
How does one replace the userID without having the originator (the user, or his/her browser on his/her behalf) send something unique to identify themselves. If you randomly walk into a library and want to take out a book, you don’t just walk out… they want to know who you are… so you provide a library card to identify who you are in their system. You can’t use a library card from another system, because they won’t know how to use that ID.
Same thing applies here. You show up at a site (sitefoo.not) and you click on log in. They don’t know if you’ve got an account, so they need you to supply something first… usually it’s your email or user ID. If they don’t have you do this (read the text above to see where they don’t mention doing this,) then what process replaces doing it so they know how to map a credential you’re about to provide and verify with your account on the system. I GUESS the site COULD look through all public keys of all users… but that is very inefficient for a busy site. If that is what they want/expect, why do they not call that out directly in their documentation. (The answer is, this is VERY BAD documentation.)
I assume it sends an encrypted blob that is the replacement for the username, the blob is decrypted and refers to a user record, the security hash in the user record is then authenticated against the key.
I understand your thinking, and it makes sense, but being that those are SUPPOSED to be developer docs, wouldn’t you seriously hope that there would be no call for assumption? In any case, it seems, that the site doesn’t initiate, but the WebAuthn/FIDO2/WebBrowser does. It can then use the site you’re on to fish out the necessary identifier from the hardware device (or software simulation of a hardware device, if you don’t care about your potential for compromise) and then negotiate a login.
I may be wrong, but my memory has it that FIDO1/U2F was initiated by the web site (or what they call the relying party.)
They don’t, based on my reading. It seems like this is a unique id for the user, stored as metadata for a particular key.
In your snippet, they say the id is furnished during the authentication ceremony. This seems like the critical component for me to understand, so here’s what I got on your original link:
Authentication ceremony
Authentication happens locally on the authenticator and is verified by the online service. First, a user will make a request to login. The online service will send the client a challenge, which the client wraps in its client data. Next, the client requests cryptographic proof of user authentication. With the user’s consent, the authenticator will return an assertion. This assertion provides evidence that the authenticator is in possession of the private key by signing the client data with the private key. The server then verifies that the client data contains the correct challenge and uses the public key to verify the signature.
So you click login to site.not. It seems like the web browser itself proves to site.not’s server that it is a bona-fide intermediary. The authentication doesn’t take place on the server, but between your browser/phone or fob.
Now I think I see your confusion, because it only communicates to the server once, so how can the browser know your id? Here’s a link I found buried to W3C spec:
A Client-side discoverable Public Key Credential Source, or Discoverable Credential for short, is a public key credential source that is discoverable and usable in authentication ceremonies where the Relying Party does not provide any credential IDs, i.e., the Relying Party invokes navigator.credentials.get() with an empty allowCredentials argument. This means that the Relying Party does not necessarily need to first identify the user.
As a consequence, a discoverable credential capable authenticator can generate an assertion signature for a discoverable credential given only an RP ID, which in turn necessitates that the public key credential source is stored in the authenticator or client platform. This is in contrast to a Server-side Public Key Credential Source, which requires that the authenticator is given both the RP ID and the credential ID but does not require client-side storage of the public key credential source.
So this is a total guess, mainly because I can’t take any more of reading this, but instead of looking you up by user name, they are indeed looking you up by user.id. The client makes you prove that you are the owner of the PK provided by the authenticator, and passes the user.id to the server. The server receives an attestation from the browser that the key is valid, that the authentication ceremony was legit, containing the public key and the user id. The server then looks up the user.id and checks that the key matches (the?) one on file.
In theory could a the server send something to the client to encrypt with it’s private key and then just iterate throught all the public keys it has till it finds a match and log in as that user?
Is there a danger with a dulicate private/public keypair?
Well, yes and no. The odds that two independent devices would ever generate the same keypair is basically zero. Unless the random number generator on both devices was borked, which HAS happened before (in the SSH and cryptocurrencies worlds.) I guess malware might intentionally interfere somehow to try to cause this?
If the server was implemented improperly, and did not validate a challenge using the public key before storing it, then it could be possible for a bad actor to copy the [potentially readily available] public key and try to act like it owns it too. The only way to “prove” someone owns the public key is to force them to use the corresponding private key. Accordingly, during a registration, or any other event where public key ownership is being contested, the server must always first establish that the other party really does know how to use the private key… EVERY TIME.
The primary difference though, in this WebAuthn world, is that the server does not verify the key. The browser proves (somehow) to the server that it is qualified to conduct the authentication ceremony, and then the key validation takes place on the user’s device. All the server receives is metadata about the user, a validation from the browser, and some other bits.
The server also sends an RP ID before authentication. I wonder what that gets used for? Maybe some kind of cryptographic test or validation that the user id the server receives matches the one on file? If that RP ID got encrypted by the private key and stored on the server’s end during registration, then that would be a simple way the server could make sure you didn’t just go in and change the user id.
No, just NO! That would be tantamount to someone walking in and saying “I’m the President” and you just believing them. There is no world in which computer authentication will ever be implemented this way. There is always a “client” desiring access and a “server” permitting access (if the correct credentials are provided) even when it’s all just done on one device. In each and every case, the client presents credentials and the server verifies them. If it’s not done this way, then you’re not actually authenticating…
That is an unfortunate misunderstanding. The relevant part to my intended meaning is here:
The private key handshake never happens on the server. That happens on the browser. Again, from the docs:
Authentication happens locally on the authenticator and is verified by the online service… The server then verifies that the client data contains the correct challenge and uses the public key to verify the signature.
The server is assured of identity by establishing a chain of trust and delegating the task of verification to the requester. So yes, the server “verifies” you but it doesn’t do it itself.
By the way, I have to nitpick the way they describe WebAuthn in these docs. The say that it’s decentralized, which is bogus. Like David Huseby said in FW 686,
decentralized is about power; computations that happen everywhere is [called] distributed.
The WebAuthn standard makes crypto happen not just between the server and client but also between the client and their own systems. But the website is literally called the “Relying Party”…
If you want to use FIDO2/CTAP2 to do passwordless authentication, you need to use one of the 25 slots allotted for that. The only way to do passwordless authentication is through FIDO2/CTAP2.
The only way to NOT use a slot, is to use FIDO2/U2F, which uses CTAP1. That requires you login with a username and password and then use the Yubikey for 2FA.
To me this has several bad implications:
If this takes off, you will need to pick and choose which sites get the “Yubikey protection.” Obviously you’ll want to protect your bank acounts, and credit card accounts first, and you’ll never be able to, because they won’t support it.
Whatever site you set up passewordless login had better be able to support multiple public keys, so you can use more than one Yubikey. I’m not going to link a site to just one Yubikey. That’s just asking for problems down the road.
This is just their bad docs spouting confusing words. What they’re actually implying, I think, is the use of the private key to compute the correct response to the server’s challenge is done internally in the Yubikey or other security device, but that would be entirely useless for authenticating if it is not sent back to the server (as I said above.) Computing the challenge response is a necessary part of authentication, but, by the definition of what authentication is, and who is requesting the user to authenticate (the server) you can’t call it authentication until the credentials are verified by the server. This just means that sentence is poor. It could say something like “the client’s response to the authentication request takes place on the user’s device” and then it would be more technically correct.
I recently attended Identiverse 2022 in Denver Colorado and attended several sessions related to FIDO2 and passkeys, as well as one entitled Bring back password: but do it right (or something like that).
First two observations from the FIDO/ passkey talks by Microsoft, Google, and the FIDO Alliance
you will not be able to sync cross platform (ad you guys have already pointed out) but if you already have a passkey on your iDevice you can log into that site on a Windows device by scanning a QR code on your iDevice which will generate the new passkey for your Windows device. It was said that this is a one time action, but they did not say if that was once to get all your passkeys onto a new platform or once per site/app.
if you loose all your devices and all your passkeys you will still be able to get into the site or app with your password. To me this seems like all FIDO2 is doing is making it look like your account is still secure as there is still that backup password in the user database somewhere that can be used to authenticate you, meaning an attacker could bypass the use of passkeys and just go after your old backup password
Unfortunately the sessions ran long (intentionally???) and there was no time for questions.
And lastly, unrelated to passkeys but something that struck me as not well though out, was the idea central to the talk on bringing back passwords.
The central theme was to use “something you do” by analyzing your typing patterns to determine if it is really you typing the password. For instance if you always pause 2ms between typing the 3rd and 4th characters in your password.
It was said there are multiple products and services that can already analyze and match typing patterns to an individual but when the presenter was asked if any sites were using this method he said “no”.
Again I did not get to ask my question.
What is there to stop a malicious actor from capturing, through a keylogger or phishing site, and replaying your typing pattern to bypass this authentication method.
Okay, well I think all of the figures on the developer docs combined with their explicit words makes it pretty clear that this is distributing the authentication client-side using a chain of trust, and that this was a specific design decision:
FIDO2/WebAuthn authentication is decentralized. Users are authenticated locally on an authenticator. The online service validates the authentication ceremony was properly conducted before allowing user access. The online service only needs publicly available information to validate the local authentication. This reduces the value of attacking the server because it has no user authentication secrets and user credentials are also not transferable between services.
Before you dismiss the Yubico docs, let’s see the W3C spec as well:
The user visits example.com, which serves up a script.
The script asks the client for an Authentication Assertion, providing as much information as possible to narrow the choice of acceptable credentials for the user. This can be obtained from the data that was stored locally after registration, or by other means such as prompting the user for a username.
The client connects to the authenticator, performing any pairing actions if necessary.
The authenticator returns a response to the client, which in turn returns a response to the Relying Party script.
The authenticator returns a response to the client, which in turn returns a response to the Relying Party script.
Remember, “authenticator” is the fob-or-fone, “client” is the browser, and “relying party” is the server.
Read more about the “assertion signature” here on the W3C spec,
an assertion signature asserts that the authenticator possessing a particular credential private key has established, to the best of its ability, that the user requesting this transaction is the same user who consented to creating that particular public key credential.
and pay special attention to Figure 4 which shows the private key being used to sign the Authentication Assertion mentioned in 2.
This is a different way to do authentication than what you’re used to. It creates a chain of trust to delegate the tasks out, not unlike the way humans accomplish this task. The last two FLOSS Weekly episodes have featured guests working on projects using similar concepts in bigger ways.
Again, no, just no. I FULLY understand the crypto, and I FULLY understand using it to do authentication. There is NOTHING new here that hasn’t been in, say, SSH, for decades. This is just a branding exercise wrapped in poorly written documentation.
There really is nothing new with using private/public keypair cryptography to authenticate yourself. The only thing new here is a codified protocol that allows you to do it over https and the marketing to sell it to the masses.
I’ve given you more than enough evidence about what is being proposed. Two separate organizations involved in the project say the same thing, in their own words. That’s not a fluke. I didn’t say you had to agree with it…
I’m curious myself how they are planning to establish trust with the browser. Does this mean that only browsers running web engines that have been compiled and signed by trusted orgs like Mozilla, Google, and Apple will be trusted delegates to verify the private key? What does this mean for DDG’s… interesting browser, or the other smaller browsers?
And, as my receipts show, a protocol to keep the private keys of users stationary at the edges while this chain of trust happens. I’m pretty worried about what this means for the small players on the Internet.