Webauthn support

Webauthn RFC

This topic aims to document the Discourse project goals around FIDO2 / Webauthn authentication.

Why?

Adding Webauthn support to Discourse will increase the security of user accounts, enabling easily acessible password-less accounts using their devices secure features, like a smartphone fingerprint reader.

Authentication Methods

  • Webauthn as a second factor authenticator (act like a Google Authenticator alternative)
  • Webauthn as a first factor authenticator (act like a social login alternative)
  • Webauthn as a multi factor authenticator (username-less login)

Webauthn as a second factor authenticator

This will allow a Discourse user, who already has an active account to use Webauthn as a 2FA, where today we only support TOTP.

Any Webauthn method can work here, be it device biometrics (fingerprint header in Android, Windows Hello laptop), a device secure chip (TPM, secure enclave) or a hardware key (like a Yubikey).

This would be availiable for every user who browses with:

  • Microsoft Edge on Windows, using Windows Hello (with facial recognition, fingerprint reader, or PIN)
  • Chrome on macOS, using Touch ID
  • Android Phone
  • Laptop/Desktop/Phone + Physical Key (Yubikey, Google Titan)

Webauthn as a first factor authenticator (password-less accounts)

Allows a user to sign in to their Discourse account using the Webauthn authentication as an alternative to a password. If a first-factor authenticator is set up, the user will be prompted to use the authenticator in lieu of a password.

The same authentication methods for second-factor authentication will work for first-factor authentication: biometrics, secure chip, or hardware key.

Register Flow

image
No password field

image

Login Flow

Webauthn as a multi factor authenticator (username-less logins)

Will expose an alternative login method that only prompts for Webauthn input. The registered security key will additionally pass user ID information to the Discourse server.

This authentication method currently requires a modern authentication key (eg a Yubikey 5) plus Google Chrome 76+, since it relies in a feature called “Residential Keys”. Since this stores data on the authenticator there can be limits, for example Yubikey 5C can only store up to 25 of those.

Register Flow

Those flows are an evolution from the one for password-less logins, not a separate login flow. This allows for a iterative implementation.


No password field, adds extra checkbox for Residential keys usage

image

Login Flow

image
If the username is left blank we will try to fetch a user_id from the autheticator

References

https://www.w3.org/TR/webauthn/

https://w3c.github.io/webauthn

Demos

https://www.passwordless.dev/overview

https://webauthndemo.appspot.com/

https://demo.yubico.com/webauthn/

Resources

https://github.com/cedarcode/webauthn-ruby

https://medium.com/@herrjemand/introduction-to-webauthn-api-5fd1fb46c285

21 Likes

Thank you for this RFC, it is quite thorough! I had a thought though about the flow for using Webauthn as a second-factor authentication method with a normal username & password login. When I have 2FA using TOTP I get this modal when I log in:

image

If a user has both TOTP codes enabled AND Webauthn authenticators, what would the flow be? Would the user decide in this modal whether they want to use Webauthn or their 2FA token? Or if this would be too onerous? Maybe Discourse could default to asking for Webauthn if the user has it set up and the browser supports it, then fall back to 2FA?

Existing Implementations

Twitter:

image
image
image

Github:


Google Account:



6 Likes

Yeah that seems to becoming the standard way to implement web authn, and I quite like the login flow. I definitely think we’ll be going in that direction here as well.

7 Likes

Thank you Jeff, that makes sense. A few other thoughts today after more investigation:

First Factor Authentication

  • If a user signs up for a Discourse account using Webauthn as a first factor authentication method, would be there a way later on for them to change to use a password instead? And if so, would the Webauthn authentication they’ve set up then fall back to being a regular 2FA method, until whichever time they want to remove it?
  • If the Webauthn was used as a first factor method, would it still show up in the UI under second factor preferences, and just not be removable?
  • Would it also be fair to say that the user the user to set up social logins in the same way they are prevented from doing so if they have 2FA enabled?
  • I’d imagine the section of the user preferences where the reset password email is sent would change too, as they would not have a password using first factor:

image

6 Likes

Text wise, I don’t like using the term “Web Authn” I think it is confusing to end users, just use “Security Key” or something like that.

I would very much like to avoid even thinking about “First factor / passwordless” auth here, to me we got to ship this feature and live with it for 3-4 months before even considering this.

Especially since we already support log in via email, so you can technically forget your password.

I agree the flow should be … if you can and have the apis and a webauthn key, try webauthn first, but give user an escape hatch. Also keep in mind you may have multiple webauthn devices, I would follow what google do here for dealing with this. (A choose another option link or something)

One thing that I do think about longer term in a separate item, we could use “discourse app” for 2fa which would be pretty cool @pmusaraj. That could make use of 2fa much more ubiquitous.

14 Likes

Yes, I agree. The “webauthn” on mockups is just a placeholder.

That said, security key doesn’t convey the fact that a user can employ their laptop/phone fingerprint/camera.

Yeah, the 3 methods presented are supposed to be implemented in the order, since 1 is a bit more simply but lays the groundwork for 2 and 3.

6 Likes

GitHub is on that same page too:

image

8 Likes

Re. “Webauthn as a first factor authenticator”, there’s discussion for for level 2 of the standard to mention the privacy implications this can have: https://github.com/w3c/webauthn/pull/1250/

Re. security key naming, I agree for the reasons outlined on the RubyGems.org PR.

I also suggested there to add a “last used for login at” timestamp in addition to security key nickname to help disambiguate them and spot potential malicious activity.

8 Likes

At work (which is a high security context) we also have an alert that emails you after a security key has been unused for 90 days, prompting you to either use it or remove it from your account.

I think implementing that at 360 days might be a good idea?

7 Likes

Great idea. Having a lower interval would be annoying as we use “infinite” sessions and I think most people will have a day to day key plus a backup one in a drawer. Not counting multiple devices native security keys.

6 Likes

I am pleased to announce that I have just merged the PR for this feature, so we can kick some webauthn tires very, very soon! :tada:

8 Likes

Just added my Android fingerprint, Yubikey via NFC and Yubikey via USB-C, using Chrome Android and Firefox Desktop and all looks ok so far.

Big bug @Martin_Brennan @featheredtoast, no way to log in on Mobile view:

Works fine on Desktop view:

10 Likes

Some random feedback :slight_smile:

This does not look right:

We should follow the composer here on margin and color of cancel.

image


Instead of `Password reset email" feels a bit like it does not belong here.

Instead maybe?

Continue cancel

Forgot password? ← in light grey


Password entry looks way big, should be a bit smaller.


I think this should say “Remove” or “Delete”


If you try to add a yubikey that you already added a cryptic error shows up.


Overall :+1: :+1: :+1: :confetti_ball:

9 Likes

Argh, I knew I was missing a route in review. Good catch :heart:

I think it’s been like this for a while, but yes these are good changes

Agree, good change.

Perhaps we can re-use the built-in chrome copy here? “You have already registered this security key. You don’t have to register it again.” is a nice clear copy.

9 Likes

Thanks @Falco and @sam for your feedback. I didn’t realise there was a different route for mobile login either! I will start work on these fixes including the password labelling/button changes tonight, hopefully even open a new PR to fix!

7 Likes

I’m really glad this worked on your Android as well (even though the mobile view is not working correctly) — I didn’t have an Android to test with.

6 Likes

May I recommend the Xiaomi Mi 9?

3 Likes

I’m not sure I’m ready to return to Android – I love my iPhone 8 too much :sweat_smile:

4 Likes

Here is the PR to fix up the above :rocket:

https://github.com/discourse/discourse/pull/8135

5 Likes

Who said return? That is old world thinking! Modern people own multiple devices :wink:

8 Likes