Using a U2F key instead of a password on Linux
This is an update and expansion on something I wrote a few years ago about
using my SoloKey U2F USB key for passwordless sudo.
Recently, I ended up typing my password into a Slack window while trying to unlock my computer. By the time I’d realised that it wasn’t locked but had merely blanked the screen, my muscle memory was far ahead of my brain. As I went through the hassle of updating my password and brain, I couldn’t help wondering whether there was a better way.
The solution I’ve found lets me unlock my computer with a short PIN and
my U2F key, and to use just the key for sudo.
These instructions are for Debian with Gnome; they will probably work on Ubuntu, and for other distributions and desktop environments you might have to make some changes.
Setting up the SoloKey
First, you need to set the PIN on your U2F key. I have an original SoloKey
(two of them, in fact), so I need to use the solo1 command. This is afflicted
by bitrot, but if you have Python installed you can work around the problem:
pip install pipx
pipx install --preinstall "fido2==0.9.3" solo1
This installs solo1 in its own Python virtual environment. You can now use
this to set the PIN:
~/.local/share/pipx/venvs/solo1/bin/solo1 key set-pin
Obviously, choose a PIN you won’t forget, and/or make a note somewhere.
If you have a different type of U2F key, you’ll have to use their tools for setting the PIN; the rest of the process is the same.
Configuring PAM
Now, install the relevant PAM library and tools:
sudo apt install libpam-u2f pamu2fcfg
Next, you need to enroll your key. Plug it in and run:
pamu2fcfg | sudo tee -a /etc/u2f_mappings
You’ll be asked to enter your PIN, then press the button. You can repeat this for any additional keys you wish to enroll.
It’s a good idea to restrict permissions on the mappings file:
sudo chmod 600 /etc/u2f_mappings
Authenticating sudo
To authenticate sudo by clicking on the key, enter the following line
into /etc/pam.d/sudo above @include common-auth:
auth sufficient pam_u2f.so authfile=/etc/u2f_mappings cue
Putting this before common-auth means that you won’t be asked for a password
if U2F authentication succeeds. Using sufficient (rather than required)
allows it to fall back to password authentication if you don’t have your key to
hand.
Save the file but don’t close the editor yet. Open a new terminal, and test that it’s working:
sudo echo OK
You should see something like Please touch the FIDO authenticator followed by
OK once you have done so.
Unlocking the computer
The procedure for unlocking is similar. This time, the relevant file is
/etc/pam.d/gdm-password, and once again we add a line above
@include common-auth:
auth sufficient pam_u2f.so authfile=/etc/u2f_mappings cue pinverification=1
The addition of pinverification=1 tells the system to prompt for the PIN in
addition to asking you to press the button. This prevents someone who gains
physical access to the key from authenticating unless they also know the PIN.
You can add the same constraint to sudo if you wish, depending on your threat
model.
Thanks to Jookia, Karubits and Yubico for helping me fill in some of the blanks.