Why adopt passkeys?
Tags: security, webdev, passkeys
Published: 2024-03-19 12:46:14

[Passkeys][passkeys] are an emerging authentication technology. Major sites including Google, GitHub and Ebay now support passkeys. In this post I will briefly explain _what_ passkeys are, but I'll focus on _why_ you should support them ... and some of the pitfalls. 

![Passkey login](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fev025nmghqw7uu2195n.png)

## Passwords are finished

Pretty much every developer and certainly every security practitioner recognises the [limitations][password-limitations] of the shared secret password model. We employ password policies to mitigate some of the risks, but even the most restrictive password policy can't protect against a site against:

1. **Phishing** - It _looks_ like your site but it isn't

2. **Credential Stuffing** - Someone used the same username/password on another site that was compromised.

## The Green Bar experiment

The industry has recognised the thread posed by phishing attacks for years. Today many people don't even know a website address, relying instead on Google or links in emails/social media. 

Even the [EV/"Green Bar"][green-bar] experiment failed to protect users from fraudulent websites. In reality, we can't rely on users to determine a website's authenticity.

## The security vs usability tradeoff

Users don't like password policies. Even in an era of password managers, many users still choose to select their own passwords. 

Rejecting a user's choice might make sense from a security perspective, but from a usability/onboarding perspective it's not great. We shouldn't have to make a usability/security tradeoff in 2024.

## Two factor authentication is a pain

Most operators recognise the problems associated with passwords and resort to secondary authentication. Typically this takes the form of SMS codes or TOTP (Google Authenticator) one-time codes.

However, multi factor authentication adds yet more friction to the signup and login process. It's also not as secure as often perceived.

Whilst one time codes make phishing attacks harder, a spoofed site can simply prompt the user to enter their code, then proxy it onto the target site in realtime. Even a "script kiddie" can do this stuff.

## Passkeys to the rescue

Today many users rely on password managers to store their passwords. The industry recognised that since we're now using our devices to remember passwords, it's time to revisit the whole concept of web authentication.

We no longer need to generate keys that can be remembered by users, in fact we don't even need to constrain ourselves to symmetric (shared secret) keys anymore. We can use computer generated asymmetric key pairs in place of passwords. That's basically what a passkey is.

Passkeys are an evolution of the Web Authentication API, an API that allows people to use "authenticators" (e.g. YubiKeys) with their browsers.

Passkeys extend the concept of an "authenticator" to the device itself (smartphone, desktop browser etc.) So there's no need for an external device.

## Client side certificates

Passkeys use a public/private key pair. The server sends a challenge, the browser/device signs the challenge with a private key and the server verifies it with the corresponding public key.

This is a vast improvement over the shared secret password model. Third party breaches are a thing of the past - private keys are never shared with websites so they can't be hacked.

Passkeys are more than client side certificates. They're associated with user accounts, not devices and a user can have multiple passkeys for a single website.

## Frictionless strong authentication

Not only are passkeys far more secure than passwords, they're also much easier to use. The browser simply creates a key pair. The public key is uploaded to the target website. No more _"Password must be N characters or longer"_ or _"You previously used that password"_ nonsense.

Authentication is equally smooth. The user clicks a button, the browser asks them if they want to log in and that's it. They may need to look at the device (Face ID) or provide their fingerprint, but it's still much quicker than copying one time codes.

## Biometric authentication

Passkeys support a feature known as _user verification_. Essentially developers can ask a device to locally re-authenticate the user before signing with a passkey. Whilst the passkey standards don't _require_ biometric verification, most devices use facial or fingerprint recognition to authenticate the user.

## Phishing resistance

It doesn't matter if two sites look identical, the browser simply won't allow a passkey created for example.com to be used on exxample.com.

This is the major advantage passkeys have over passwords. It's the device that decides whether to "enter" a passkey on a site, not the user.

## Browser support

Most browsers now [support passkeys][browser-support], although support for some advanced capabilities remains limited.

## Drawbacks and pitfalls

As I've been evangelising about passkeys, it's only fair to highlight some of the drawbacks. Some of these issues are being addressed by the W3C and FIDO working groups but this is the state of play as of April 2024...

1. **User awareness** - Most people haven't heard of passkeys. If you're target audience is tech savvy you'll have few issues, but other users will need some education and persuasion.

2. **Browser support** - Most browsers now support passkeys, but if you need to support "legacy" browsers passkeys won't be an option.

3. **Javascript** - Users **must** have javascript enabled, as the underlying APIs can only be accessed using script. 

4. **Browser quirks** - Like any new technology, passkeys are not without bugs. I've run into countless bugs and quirks. Fortunately, things are improving.

4. **Same site restrictions** - Passkeys can only be used on the host/domain for which they were created. However, this phishing protection is a double edged sword...

### Same site restrictions

The same site restriction works similarly to cookie same origin policies. A passkey created for example.com can be used on en.example.com and de.example.com, but en.example.com can't be used on de.example.com.

The problem arises when we want to change domains. Whilst we can redirect users (and search engines) from old.com to new.com, the old.com passkey won't work on new.com. 

This is a major issue and it is being addressed by the standards bodies. In the meantime there are a couple of workarounds that can be applied.

### Same site workarounds

Firstly we can authenticate a user on old.com **then** redirect them to new.com. Of course we can't set a cookie, but a JWT would work well in this scenario.

Once authenticated we can then prompt the user to create a new passkey for new.com so they can sign in directly in future.

We can also adopt a process similar to the reset password flow. Assuming we have the user's email address (and trust their mailbox security) we can email a secure "create passkey" link to new.com.

## Adopting passkeys

I hope I've persuaded you to at least evaluate passkeys. If you're looking for a quick start guide please see my [How to add passkey login][supporting-passkeys] post here on dev.to and do let me know if you have any questions. Thanks for reading!

[passkeys]: https://developers.google.com/identity/passkeys

[password-limitations]: https://passlock.dev/blog/authentication/password-issues

[green-bar]: https://en.wikipedia.org/wiki/Extended_Validation_Certificate#Removal_of_special_UI_indicators

[browser-support]: https://passlock.dev/blog/passkeys/passkey-browser-support-2023

[supporting-passkeys]: https://dev.to/toby_hobson/adding-passkey-authentication-to-web-apps-ai1