FIDO2 Fiasco
My fellow-ex-co-worker and I are working on a system we have hopes of selling in a little niche market in my country.While it is still in its infancy, we both know we'll have to implement some kind of authentication subsystem to it eventually.
We have done so in the past and I always asked myself, in this CCPA and GDPR days and era, it has to have something out there better than user/password stuff.
While I was browsing the Internet the other day, something caught my eye: A protocol called WebAuthn, that I have never heard of before.
It is something brilliant composed of three parts: First there is the Authenticator. In Windows-land, it can be what is called "Windows Hello."
(It can also be some other means like YubiKey, for instance.)
It is something available in Windows 10 that can authenticate you by recognizing your face, your fingerprint, or through a PIN
Face and fingerprint recognition need specialized hardware, that I do not have, so PIN would have to suffice.
The second part is browser support. The browser has to support WebAuthn API. The browser I use - that's not IE, Edge, Firefox, nor Chrome - supports it.
The third part is the server, that is, the site where the user wants to register or log in. In other words, our under-construction niche-system.
How it works
From what I could get, in broader strokes, it works like this:- The user goes to a register page;
- That page sends some information to register subsystem and receives some data back from it;
- As in the next step we'll need to provide to WebAuthn API at least a user name, a user display name, and a bunch of bytes signed by a private key, it is a good idea to send the first two pieces of data (user name and user display name) in the request above, so they can be validated by the server before stepping into WebAuthn API land. This way the register subsystem can check if the chosen user name is available and if the user display name is within acceptable length constraints, for instance;
- About that bunch of bytes, they need to be provided by the register subsystem and returned as response to that request we mentioned above. They need to be random and to have at least 16 bytes.
- Another piece of data that's needed from the server and should be provided in the response is its ID (called origin.)
- Upon checking that the request to register has been accepted - the user name is available and the user display name has a reasonable length in our example - the page concocts an options Javascript object and calls browser's navigator.credentials.create method. (I'm skipping the part that checks whether the browser supports WebAuthn API or not, but it has to be there.)
- This call goes to Authenticator. It authenticates the user through whatever means the user had set up - face, fingerprint, or PIN - and returns another object that's meant to be sent to the server. This object has a public key that was created by the Authenticator while creating the public/private keys pair.
- It also has that bunch of bytes signed by the private key. By the way, the "bunch of bytes" is called challenge.
- Now the page needs to send to the server the object returned by navigator.credentials.create call - after some bits have been massaged by the page itself, like transforming Javascript's ArrayBuffers to base-64 strings.
- The server has to validate what it has received - following not less than 19 validation steps - and, if everything is OK, let the user know that they are registered.
- The server has to save at least the user's user name and the object containing the user's public key so the user can log in later.
When a user wants to register themselves to a WebAuthn-compliant site, they start a process that:
- will authenticate them locally,
- will create a pair of keys that will be stored locally,
- will use the private key part of the key pairs to cryptographically sign a bunch of random bytes (challenge) provided by the site,
- will send the user's user name, display name, signed bytes, and the public key part of the keys pair to the site.
To log in, the process is almost the same, but simpler. It uses the browser's navigator.credentials.get method instead of create and does not need user's or server's information to be exchanged.
What are the pros?
- Depending on some parameters I won't go into details because I don't actually understand them when saving user's data in the server, there's nothing there that allow us - or anyone else - to track user back. There's no identifiable information to use. We have a user name and a public key, and that's it.
- The user is authenticated by the Authenticator, not by the server/site. Their secret key is there, in their machine, too (or in a YubiKey.)
If a hacker gains access to your site, there's nothing useful there to sell, explore, or blackmail.
What are the cons?
- I have no clue how it can be used in non-Windows OSes.
- At first sight, if not using something like YubiKey, it seems the user would only be able to log in from the same machine they registered.
I've read somewhere that the user would be able to register other devices, but I have no idea how. I did not search hard enough to see how this can be accomplished.
What else?
There are some sites where you can test this whole process, but first I needed to set up my Windows Hello.I went to Start → Settings and searched for Windows Hello. I've been presented with Sign-in options / Sign-in settings with PIN (recommended) (or whatever. I could not find the exact text in English.)
After going through the step by step to set up my PIN, I've received some BS message error.
I re-tried it some more times, but all ended up the same way. Worst, now instead of the previous message, it said Windows Hello was not available.
Going to the suggested site in the error message (http://aka.ms/PINError) with the error code shown (0x801c004d) was fruitless. That specific error code is not listed there.
Great.
Let's use Windows troubleshoot 101: Reboot laptop.
After rebooting, I was requested my PIN. Wha...? OK, PIN provided. Went back to Windows Hello and the not-available message was still there. Uh, whatever.
I've tried first this site but it kept asking for my non-existent key USB. Annoying.
Then I've tested this one and this time it asked for my PIN.
I went through the steps and all in all it seems it can be useful. I've found some Javascript examples that could be adapted to my needs and a .NET library that could be used on the server-side.
But if I had a hard time setting up a half-baked PIN on my own machine, what about my future customers?
Also, I first intended to use Windows Hello only to authenticate myself to a site. I had no wish to give up my Windows log-in password at all.
What about my future customers? Would they change their already-in-place users' authentication process to meet my needs? Probably not.
So, test completed, now is time to get rid of Windows Hello PIN and get back my faithful password. But, but, but... Windows Hello is not available!
Time to some DuckDuckGo-Fu. First tip: Make sure your Windows is up to date. The problem is, mine is not.
What???
Once upon a time, I had my Windows Update on. So, Windows Update did what Windows Update does and it updated my Windows. After the first reboot, the password box on my login page was nowhere to be seen. I was no longer able to use my laptop.Using my wife's laptop and my cellphone, I searched how to fix this MS f**k-up. Few hits and none worked.
Windows Restore? Done, no dice.
Protected mode? Yeah, not going to help.
After some frustrating hours, I swallowed the pill and formatted my laptop. I had around two days of "fun" reinstalling everything I use and restoring personal data. By sheer luck, I was not requested to work during this time.
"Fool me once" and all, I turned off Windows Update. Six months later I manually let the updation* begin and, luckily, when it was done I was able to log in. Yay, I guess?
Alas, it was seven months ago.
I checked how many packages were going to be installed: Nine.
Letting it go, all of them were downloaded and the first one started installing. I can't remember at what percentage it froze. I guess it was around 90-something.
You see, the last time my Windows froze, I was unable to restart my machine because it did not respond to Ctrl+Alt+Del, Ctrl+C, closing the lid, or even pressing the power button.
My laptop is not one of those you can simply remove the battery, you have to unscrew the case to get access to it. No way I was going to do that.
So, without alternatives, I unplugged it from the power outlet and let it die slowly.
Thinking I would need to do the same this time, that's what I did.
After a few hours, nothing changed, but I noticed the mouse cursor was responsive. So I tried the power button and it worked. Good. I have "only" lost half a day on this.
Then I lost the following day updating Windows, rebooting, and the whole shebang.
When it was finally done, I went back to Windows Hello to learn it was still unavailable. Is it depressing to say I saw it coming?
So, I tried the second tip: Running SFC /Scannow .
It said it found some corrupted files but was unable to restore them. Somehow I too was unable to make it work. I did not understand its online or offline options.
The third tip was to run DISM.exe /Online /Cleanup-Image /Restorehealth . I have to confess I was too afraid to run it, so I passed on it.
Fourth tip: Run Clear-Tpm in Powershell. Useless.
Then, the last one: Run certutil -deletehellocontainer . It is a little frightening, but what else could I do? I run it, rebooted, and my password was requested. Phew!
Final notes
Despite my non-enjoyable experience with Windows Hello, WebAuthn is a good alternative to user/password, as long as my non-existent-customers are already on the Windows Hello bandwagon.By the way, FIDO2 is a joint effort between the FIDO Alliance and the W3C that produced the WebAuthn standard.
*I know this word is not usual in American English, but I could not resist. :)
Next week we'll go back to our transpiler series.
Andrej Biasic
2021-08-25