A look at password security, Part IV: WebAuthn
As discussed in part III, public key authentication is great in principle but in practice has been hard to integrate into the Web environment. However, we’re now seeing deployment of a new technology called WebAuthn (short for Web Authentication) that hopefully changes that.1
The key difference here is that previous systems tended to operate at a lower layer (typically HTTP or TLS), which made it hard for the site to control how and when authentication happened.2 By contrast, a JS API puts the site in control so it can ask for authentication when it wants to (e.g., after showing the home page and prompting for the username).
Some Technical Details
- makeCredential: Creates a new public key pair and returns the public key.
- getAssertion: Sign with an existing credential over a challenge provided by the server.
The way this is used in practice is that when the user first registers with the server — or as is more likely now, when the server first adds WebAuthn support or detects that a client has it — the server uses
makeCredential() to create a new public key pair and stores the public key, possibly along with an attestation. An attestation is a provable statement such as, “this public key was minted by a YubiKey.” Note that unlike some public key authentication systems, each server gets its own public key so WebAuthn is harder to use for cross-site tracking (more on this later). Then when the user returns, the site uses
getAssertion(), causing the browser to sign the server’s challenge using the private key associated with the public key. The server can then verify the assertion, allowing it to determine that the client is the same endpoint as originally registered (for some value of “the same”. More on this later too).
The clever bit here is that because this is all hidden behind a JS API, the site can authenticate the client at any part of its login experience it wants without disrupting the user experience. In particular, WebAuthn can be used as a second factor in addition to a password or as a primary authenticator without a password.
The WebAuthn specification doesn’t require any particular mechanism for handling the key pair, so it’s technically possible to implement WebAuthn entirely in the browser, storing the key on the user’s disk. However, the designers of WebAuthn and its predecessor FIDO U2F were very concerned about the user’s machine being compromised and the private key being stolen, which would allow the attacker to impersonate the user indefinitely (just like if your password was compromised).
Accordingly, WebAuthn was explicitly designed around having the key pair in a hardware token. These tokens are designed to do all the cryptography internally and never expose the key, so if your computer is compromised, the attacker may be able to impersonate you temporarily, but they won’t be able to steal the key. This also has the advantage that the token is portable, so you can pull it out of your computer and carry it with you — thus minimizing the risk of your computer being stolen — or plug it into a second computer; it’s the token that matters not the computer it’s plugged into. We’re also starting to see hardware backed designs that don’t depend on a token. For instance, modern Macs have trusted hardware built in to power TouchID and FaceID and Apple is using this to implement WebAuthn. We have been looking at similar designs for Firefox.
While hardware key storage isn’t mandatory, WebAuthn was designed to allow sites to require it. Obviously you can’t just trust the browser when it says that it’s storing the key in hardware and so WebAuthn includes an attestation scheme that is designed to let the site determine the type of token/device being used for WebAuthn. However, there are privacy concerns about the attestation scheme 3 and many sites don’t actually insist on it. Firefox shows a separate prompt (shown below) when the site requests attestation.
Privacy Properties and User Interactivity
While as a technical matter a browser or token could just do all the WebAuthn computations automatically with no user interaction, that’s not really what you want for two reasons:
- It allows sites to track users without their consent (this already happens with user login fields which is why Firefox requires that the user interact with the page before filling in your username or password.)
- It would allow an attacker who had compromised your computer to invisibly log in as you.
In order to prevent this, FIDO-compliant tokens require the user to do something (typically touch the token) before signing an assertion. This prevents invisible tracking or use of the key to log in. Apple’s use of FaceID/TouchID takes this one step further, requiring a specific user to authorize a login, thus protecting you in case your laptop is stolen.
If you’re familiar with Web technologies, you might be wondering why we need something new here. In particular, many of the properties of WebAuthn could be replicated with cookies or WebCrypto. However, WebAuthn offers a number of advantages over these alternatives.
First, because WebAuthn requires user interaction prior to authentication it is much harder to use for tracking. This means that the browser doesn’t need to clear WebAuthn state when it clears cookie or WebCrypto state as they can be used for invisible tracking. It would be possible to add some kind of explicit user action step before accessing cookies or WebCrypto but then you would have something new.
Technically, WebAuthn is a pretty big improvement over pre-existing systems. However, authentication systems tend to rely pretty heavily on network effects: it’s not worth users enabling it unless a lot of sites use it and it’s not worth sites enabling it unless a lot of users are willing to sign up. So far, indications are pretty promising: a number of important sites such as GSuite and Github already support WebAuthn as do SSO vendors like Okta and Duo. All four major browsers support it as well. With any luck we’ll be seeing a lot more WebAuthn deployment over the next few years — a big step forward for user security.
Up Next: Login and Device Encryption
This about wraps it up for remote authentication, but what about logging into your computer or phone? I’ll be covering that next.
Thanks to JC Jones and Chris Wood for help with this post.
- The WebAuthn spec is pretty hard to read. MDN’s article does a better job. ↩
- For instance, with TLS the easiest thing to do is to authenticate the user as soon as they connect, but this means you don’t get to show any UI, which is awkward for users who don’t yet have accounts. You can also do “TLS renegotiation” later in the connection but for a variety of technical reasons that has proven hard to integrate with servers. In addition, any TLS-level authentication is an awkward fit for CDNs because the TLS is terminated at the CDN, not at the origin. ↩
- The idea behind the attestation mechanism is that the device manufacturer issues a certificate to the device and device uses the corresponding private key to sign the new generated authentication key. However, if that certificate is unique to the device and used for every site then it becomes a tracking vector. The specification suggests two (somewhat clunky) mechanisms for reducing the risk here, but neither is mandatory. ↩