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.