Implemented Password-less Login Using Web Authentication API (WebAuthn)

This suggestion has been implemented. Votes are no longer accepted.
Registration would be a little kludgey, because you still need the user to pick a username (and probably an email address) when they register (but before they use their security key). You can't have a XF user without a username, so there's that (no way around them needing to pick a username). And at that point, you aren't saving a whole lot of time/energy for the registering user (they are needing to more or less do all the normal stuff at registration except pick a password, and instead of doing that, you are giving them something new to do [use the security key]).
Does the same issue arise on login?
 
Does the same issue arise on login?
Ya... you would need to give your username before the JavaScript triggers the method to authenticate the user with their security key. I was hoping for a situation where you could just come to the site and authenticate with the security key and that was it. But it's not that simple (unfortunately).

Like I said in the post, personally I think it's really well suited as a two-step verification system (where you already know which user it is), but not so much for straight authentication.

Ideally, you pass the allowed credentialIds (a WebAuthn thing) to the method that starts the verification (it's how the browser knows which credentials should be used, since the security key generates a new set of public/private keys for every site... otherwise when you ask the security key to sign the challenge, it wouldn't know which key to sign it with)... which means a user needs to enter their username, the system loads all the credentialIds that user has and then passes them to the JavaScript object to perform the client-side verification... credentialIds aren't anything crazy (like they are just that... IDs... nothing about the user), however it still feels weird to me that someone could (in theory) give a username and see exactly how many security keys someone has setup on their account. Again, just feels better to be disclosing that only if the user actually authenticates first (and done as part of the two-step verification flow).
 
Last edited:
I went ahead and built a XF2 add-on the allows security keys to be used for two-step verification. My thought was to build that first (since that was more useful to me than the straight password-less login system) and then see about doing the password-less login system after the fact.

In building the two-step portion, I learned a whole lot about WebAuthn, and to be honest, I don't think it's a really good fit for password-less logins, and here's why...

Both the registration and authentication functions require that the end user pick a username before doing the trickery with the security key. For example, in order for an existing user to use it to log in, it's not as simple as just using the security key... you also need to manually enter your username (at minimum). The technical reason for this is because when you request a user to authenticate with the key, you have to tell the API which credentials you already have that you will accept. The allowCredentials option in the spec is technically optional, but for practical purposes with XenForo, it's not without major schema changes. I'm doing it by loading multiple security key credentials into a single xf_user_tfa.provider_data column. For two-step verification, I simply pull the record for that user, then look in the json array to see if the given credential matches. It's a lot more difficult going the other direction (where you might have a credentialId, and need to find which user it belongs to). Unless you created a whole new table to store security key credentials, it's not (realistically) a query you can do.

Registration would be a little kludgey, because you still need the user to pick a username (and probably an email address) when they register (but before they use their security key). You can't have a XF user without a username, so there's that (no way around them needing to pick a username). And at that point, you aren't saving a whole lot of time/energy for the registering user (they are needing to more or less do all the normal stuff at registration except pick a password, and instead of doing that, you are giving them something new to do [use the security key]).

You can kind of see what I mean with the demo here: https://webauthn.io/ ...you can't Register or Login without giving it your username first. It's not like you just come to the site and use your security key and are good to go. There's more to it.

Note about non-hardware security keys... you can use them, but it's really not that great for portability reasons because the security key is the physical device itself... like I can setup a security key based on Face ID of my phone, but that doesn't carry over to an iPad or macOS with the same Apple ID. This also means if my phone is replaced or lost, that security key is also lost. You can have multiple security keys, so if one wanted to go through the hassle of registering every possible device as a security key, I guess you could do that and unregister/reregister a new one if it's replaced. But that seems like a hassle to me... the YubiKey 5 NFC is the way to go for me... if I have a USB port or an NFC-enabled phone, it works with it all as a single security key that you can use with future devices.
Is this something you might consider sharing please..? :D
 
Both the registration and authentication functions require that the end user pick a username before doing the trickery with the security key. For example, in order for an existing user to use it to log in, it's not as simple as just using the security key... you also need to manually enter your username (at minimum).
I might be missing smth. but entering a username does not seem to be required if the security key does support redident keys (Yubikey 5 does).
 
Is this something you might consider sharing please..? :D
Ya, at some point... I'm rolling it into my internal "Security" addon that does some other things (and I still have some additional things to do for it).

I might be missing smth. but entering a username does not seem to be required if the security key does support redident keys (Yubikey 5 does).
It might be possible technically (I haven't messed with it myself), but it's definitely not ideal with how XenForo works internally. If the WebAuthn is able to return a credentialId blindly (without being given a list of ones it will accept), in order to look up that credentialId on the XenForo side, XenForo would require a new table to track security keys on a per record basis (you would need to be able to search on that credentialId, which I touched on a little in this post:
The technical reason for this is because when you request a user to authenticate with the key, you have to tell the API which credentials you already have that you will accept. The allowCredentials option in the spec is technically optional, but for practical purposes with XenForo, it's not without major schema changes.
Again, I haven't tried it myself because I was trying to package my thing into XenForo's existing framework and authentication flow (and not require any schema changes). The YubiKey (and others) store the domain scope for the credentials, so it could in theory return whatever credentialId belongs to that domain without you telling it which credentialIds are allowed. However, I can see how that could go wrong and become a support issue... for example, my YubiKey probably has 8 or 9 different credentials for my site from when I was testing things. Which one would it return if I didn't give it a list of credentials I care about? Could be a problem if someone deletes their security key from a site and then re-adds it (and now the YubiKey has multiple credentials for the site... it generates a new one, it doesn't reuse an old one).

The biggest issue for me is that I didn't want to add new tables for this, and blindly receiving a credentialId from the key (ignoring the issue of how the key knows which credentialId for a site to send) without a username would require that (you could get away with it if users were limited to a single security key, but security keys should be a one to many relationship in case a user loses one).

Ultimately when used as a password-less system (rather than a two-step verification) hardware keys aren't quite as clean/simple. There's also a potential security risk, if someone gets your security key, do you really want them to be able to log into sites by clicking a button (you could work around that with security key PINs, but then that's an added hassle for normal use... at which point why not just use a password like normal instead of a PIN and use the key as a two-step thing... either scenarios you are entering something outside of the hardware key button click... a PIN or a password). And I can see why most major companies that use them, use them just for two-step verification. With everything I use it with, Github, Google, Vanguard, Facebook, Kraken, Twitter, Cloudflare, etc., I have yet to see any of them use it for password-less registration/sign in. There's the technical issues of how data is stored, issues when you have a situation where a security key has multiple credentials for a single domain, and then there's just the UI/UX of it... You would end up with two totally different registration/login systems/flows (sometimes you pick a username/email/password, sometimes you just click your USB key and then pick a username/email) which can lead to confusion for users. They click the wrong thing and now they are being asked to click their USB key button when they just wanted to register as a new user.

Anyway, ya... it's possible from a technical standpoint (with a few caveats).

A true password-less system would be better suited to a system that didn't try to cater to some users doing password-less and some users not. With XenForo, a password-less authentication still would require the user to pick a username and email so you aren't really saving much time/effort during registration. I could see where it would be more useful for something like a company's internal application for employees, where they issue YubiKeys to employees (and they aren't collecting username or emails), and that's the ONLY option for logging in/registration (not trying to support alternate methods).
 
Last edited:
Apple, Google, and Microsoft are joining forces to push passwordless sign-ins. Below are two highlights of the new capabilities that will address some concerns raised by @digitalpoint above.
  1. Allow users to automatically access their FIDO sign-in credentials (referred to by some as a “passkey”) on many of their devices, even new ones, without having to re-enroll every account.
  2. Enable users to use FIDO authentication on their mobile device to sign in to an app or website on a nearby device, regardless of the OS platform or browser they are running.

 
Apple, Google, and Microsoft are joining forces to push passwordless sign-ins. Below are two highlights of the new capabilities that will address some concerns raised by @digitalpoint above.


Ya, I saw that the other day. It shouldn't be a difficult thing to implement either because the core functionality is already there. All they need to do instead of storing the private key strictly on the device itself, store the private key in something that already exists (for Apple users, that would be their iCloud Keychain). Do that, and you have portability across all your devices (and to new future devices). Would be much more convenient at that point.

If they simply do that (which is what I'm expecting them to do), it also means existing implementations of WebAuthn/FIDO2 (like the addon I made) don't need to be updated either.
 
Just read that in an IT newsletter I get. I know the security analyst at our corporate parent is itching to get rid of passwords at work. Windows Hello would be the solution there since we are an all (well, mostly) MS world.
 
I released my implementation of WebAuthn/FIDO2 to allow for hardware security keys as a two-step authentication system in XF2. Has some other features too, but that's the biggie.

 
I have split the posts off to a new thread so the discussion can continue outside this suggestion thread.

 
Our passkeys implementation is debuting in XF 2.3!

More details:
 
Back
Top Bottom