Webauthn: What's this SPEC for?

Created on 24 Feb 2018  Â·  14Comments  Â·  Source: w3c/webauthn

Is this SPEC for something like this proposal

  1. User has a private-public key pair.
  2. User visit a website.
  3. User send the public key to the website server.
  4. Website server generate a random code, use the user's public key to encrypt the random code, and send the encrypted code to the user.
  5. User use his private key to extract the origin code, and send it to the website server.
  6. Website server authenticate the user.

Is this SPEC like above description?

Of course, user can have many private-public key pairs. And select one when visit a website.

And for the sake of privacy(two website account should not know each other), maybe it's not private-public key pair. It's one private key with many public keys, a big private-publics key pair.

And for the sake of managing the public keys, the public keys should be generated according the website origin rather than randomly.

Is this SPEC like this? Or just like ZeroNet's user.json file?

If not, then what's the purpose of this SPEC?

editorial

Most helpful comment

This is not an appropriate use of the issue tracker, because it is not making actionable proposals about potential changes to the specification. If you want to have a general discussion about the specification and its goals, it should happen on the [email protected] mailing list.

All 14 comments

Almost, but there are some important differences. Web Authentication does not assume that the user has a universal identity that they use for all websites, instead a new identity (_credential_) is created for each website. The purpose of this spec is

  • to provide websites with a widely available API to authenticate users with strong asymmetric cryptography.
  • to provide users with a solution to be much more secure with less effort. They don't need to remember any passwords. Instead they can use a single hardware key (_authenticator_) to securely log in everywhere, but without the risk that hackers could steal the key on one site and use it on another.

The following is a bit simplified, but describes the most important parts.

First, the user creates a new account or registers a new _credential_ (public-private key pair) to an existing account on the website:

  1. User has an authenticator that can create and store credentials (private keys). An authenticator could be a software program, a TPM (trusted platform module) built into a computer/phone etc, an external USB/Bluetooth/NFC device on their keychain, or a future invention.
  2. User visits a website and goes to register a new credential for their account.
  3. Website sends a random _challenge_, a random _user ID_ (not username) and a (possibly empty) list of public keys the user has already registered.
  4. User selects an authenticator that does not contain one of the already registered credentials.
  5. That authenticator creates a new credential, stores the website domain and user ID with the credential and _signs_ the challenge, the public key and the website domain with an _attestation private key_.
  6. User agent sends the signature, the public key and the _attestation certificate_ back to the website.
  7. Website verifies the signature over the challenge and public key.
  8. Website optionally inspects the attestation certificate and decides if it wants to trust the authenticator. The attestation certificate encodes information about the security properties of the authenticator, so a bank might for example choose to only trust TPMs and external hardware authenticators, and not software authenticators or unknown ones.
  9. If the website decides to trust the authenticator (or doesn't care about the authenticator type), it registers the credential's public key with the user's account.

The next time the user visits this site:

  1. User enters their username and password.
  2. Website sends a random challenge and a list of public keys the user has registered.
  3. User plugs in an authenticator if necessary, then selects one of the credentials in the list.
  4. The authenticator that contains the selected credential signs the challenge and the website domain using the credential's private key.
  5. User agent sends the signature and public key back the the website.
  6. Website verifies that the public key is registered to the user, verifies the signature and then logs the user in as the given username.

This is the "second factor" use case. Alternatively, some authenticators and websites support a "first factor" use case making it possible to log in without even a username:

  1. User requests to log in.
  2. Website sends a random challenge.
  3. User selects any credential bound to the website.
  4. The authenticator containing the selected credential authenticates the user, for example using PIN or fingerprint.
  5. Authenticator signs the challenge and the website domain.
  6. User agent sends the signature, public key and user ID back to the website.
  7. Website verifies that the public key is registered to that user ID, verifies the signature and logs the user in as that user ID.

Does this answer some of your questions?

@emlun: This is a pretty good functional explanation, at least for me. Would it be feasible to put it as an explainer into the readme or the spec introduction?

@emlun Thank you very much for this detail explanation. But I still have some tips don't understand:

  1. Should the authenticator store the credentials for every site? In other words, if I use a software authenticator and the software is offline(ie it can not sync between different PCs), then when I use this SPEC register an account in a site, I can not use this account when I use another PC unless the two PCs' software authenticators are synced. Is it ?

    Or just store only one private key and use some method like md5(user.private_key + site.origin) to generate the user identity for the site instantly. I vote to this method because no sync is required. Of course, if people need two or more accounts in just one site, (s)he can have many private keys.

  2. 5. That authenticator creates a new credential, stores the website domain and user ID....., what if the website change their domain or origin? Like www.youtube.com and m.youtube.com and google.com and alphabet.com.

  1. Yes, there will be a different key for each site, but you can register multiple keys with each account. A likely scenario for many users will be to use a built-in authenticator most of the time, but also have an external authenticator for logging in from a new device. After that first login you can register the built-in authenticator in the new device (if it has one) so you don't need the external authenticator for future logins on that device.

But "store the credential" was a simplification. What's actually sent back to server is a public key and a _credential ID_. If the authenticator stores the private key, the credential ID will just be a random byte string. But the authenticator may also choose to instead encrypt the private key using an internal encryption key, and send the encrypted private key as the credential ID. In this case the key is actually stored on the server (but note that the server still only sees a blob of random bytes), and can be used by any authenticator with the same internal encryption key. This also means the authenticator has infinite "storage" capacity for such credentials. This is how existing U2F security keys work. Note that in this case it's not possible to use the credential in "first factor mode" as described above, because in that mode the authenticator doesn't get the credential ID from the server.

I vote to this method

Web Authentication does not specify the details of how the authenticator creates or stores the keys. Authenticator vendors are free to implement it how they wish, as long as they're compliant, and users are free to choose which authenticators they want to use.

  1. Then the credential won't work anymore. The server can "override" the origin as long as it stays within the same domain, though, so www.youtube.com can set its origin to youtube.com so credentials created there are also usable on m.youtube.com.

It should actually be possible for authenticators to provide a way to change the domain a credential is bound to, but no such feature is defined in the spec.

note that we already have the https://www.w3.org/TR/webauthn/#use-cases section, which provides a higher-level summary of the above scenarios. So I'd interpret this issue as one suggesting adding clarification and detail (in some fashion) for technically-inclined readers. see also PR #375.

The use cases are good. This spec jumps right into technical details and terminology without describing the high-level goals, so a bit of text about that in the intro would be helpful - e.g. stuff like this from @emlun: "Web Authentication does not assume that the user has a universal identity that they use for all websites, instead a new identity (credential) is created for each website."

Then the credential won't work anymore.

If it's like this. Why not use a much simpler way for authentication.

  1. user generate a uuid as his/her identify on the whole www net.
  2. browser give an api generate_identity = () => md5(user.uuid + location.host).
  3. website javascript run const identity = generate_identity()... whoever has the identity has the account.
  • websites don't know each other since they can only get the md5 result.

Well, things will be better if websites can change their domain.

The problem Web Authentication aims to solve is easy multi-factor authentication (MFA), not global identities.

I don't understand what problems your solution would solve. Do you mean that knowledge of the generate_identity() result would be enough to prove ownership of the user.uuid identity? I don't see how that would be any more secure or easy to use than a conventional session cookie, if the identity is never shared between websites anyway.

Well, things will be better if websites can change their domain.

Why would it be better? How often do the websites you frequent change their domains? And how would your suggested generate_identity() solve that?

Binding credentials to the websites they were created for is one part of what makes Web Authentication credentials practically immune to phishing and similar spoofing attacks.

I don't understand what problems your solution would solve.

  1. The user needn't to remember so many usernames and passwords. He/She just need remember a uuid, everything is done. One uuid can be used in every website.
  2. Different PCs or different browsers needn't to sync data.
  3. Register an account will be very easy.

And how would your suggested generate_identity() solve that?

No, I don't know how to solve that. I just wish if there is a solution.

  1. The user needn't to remember so many usernames and passwords.

Web Authentication hopes to solve that as well. It will be up to each website to choose whether it still wants to use a username and/or password in addition to a Web Authentication 2nd factor, but it's perfectly possible for a website to use only a Web Authentication credential to identify and authenticate a user. From the user's perspective you could have a single PIN-protected security key on your keychain, and that security key is your "username" and "password" for as many websites as you want.

He/She just need remember a uuid, everything is done. One uuid can be used in every website.

Sorry, but I don't think asking people to remember 16 random bytes would be feasible. Even if it was, this would not be significantly better than a standard password. If the user is tricked to reveal their UUID - by a phishing attack, for example - then all their accounts everywhere on the web are taken over. By contrast, a Web Authentication credential cannot be stolen in this way because the private key never leaves the authenticator.

  1. Different PCs or different browsers needn't to sync data.

They don't need to sync anything to use Web Authentication credentials either. A platform credential will of course only be usable on a single device, but an external authenticator can be used on any device.

  1. Register an account will be very easy.

It will be very easy for the user with Web Authentication as well - arguably easier than registering an account with a password, in the simplest case. One possible example:

  1. User visits example.com on their phone.
  2. example.com asks if the user wants to create an account.
  3. User clicks "yes".
  4. Browser asks the user to type a PIN or scan their fingerprint.
  5. example.com confirms that the account has been created and logs the user in.

by a phishing attack

User needn't to tell websites their uuid. User just need to tell the browser their uuid when the browser is opened first time. And in fact, people may not remember their uuid, they just store it in a usb device. So, when the browser is opened at the first time, user need import a uuid into browser. Then, when the user visit website, he/she just click confirm button. Browser doesn't expose the user.uuid to the JS runtime, it just expose function generate_identity = () => md5(user.uuid + location.host).... So it has nothing to do with phishing attack.

They don't need to sync anything to use Web Authentication credentials either.

I think sync is a big demand. I have imported the same uuid to two different browser: one PC browser and one mobile browser. Then when I visit a website at the first time on PC, and use const identity = generate_identity() the identity registered an account, and did many things using the account. Then when I visit the website on mobile browser, I got the same account and those things I did on PC is naturally showed on mobile browser.

It will be very easy for the user with Web Authentication as well

Yeah, our two solutions are both easy to register.

In fact, the main difference between the two solution is: who is the authenticator. Your authenticator is a software, a usb device. My authenticator is Math.

The user doesn't _need_ to know their UUID, but if there is a way to export it (for syncing, for example) you can be sure that some clever phishers will succeed to "help" some users find and enter their UUID into a form to "confirm your PayPal account". It is impossible to make this mistake with a Web Authentication hardware authenticator.

I think sync is a big demand.

Again, no sync is needed to use an external authenticator on a new device. You just plug it in and log in. Then if you want you can register a platform credential on that device, if the device supports it, so you don't need the external authenticator the next time you log in to that account.

You just plug it in and log in.

So, this spec is to reinvent LastPass(a software which help manage you accounts) plus an username_generator.

last_pass = password_generator + account_manager
spec = last_pass + username_generator
spec = password_generator + username_generator + account_manager
spec = account_generator + account_manager

This is not an appropriate use of the issue tracker, because it is not making actionable proposals about potential changes to the specification. If you want to have a general discussion about the specification and its goals, it should happen on the [email protected] mailing list.

Was this page helpful?
0 / 5 - 0 ratings