Skip to content

Passwordless or MFA with Yubikey

I use Ubuntu and Yubikeys but this works for other security keys and Linux OSes as well.

Prerequisites

Install required software.

sudo apt install libpam-u2f

Add your Yubikeys to the system

Create the directory.

mkdir -p ~/.config/Yubico

Add your first Yubikey (we will add additional keys later).

pamu2fcfg > ~/.config/Yubico/u2f_keys

Press they key when it's flashing.

To add additional keys (highly recommended).

pamu2fcfg -n >> ~/.config/Yubico/u2f_keys

And again, press they key when it's flashing.

Authentication possibilities

You can pick and chose how you want to use your Yubikeys.
Add the cue option to display "Please touch the device." message.

MFA

The MFA method - this will require a password and then the Yubikey.

@include common-auth
auth       required   pam_u2f.so cue

Passwordless

The passwordless method - this will require the Yubikey only.

#@include common-auth
auth       required   pam_u2f.so cue

Fallback

The fallback method - this will prompt for Yubikey but if it's not found it will fallback to password.

auth    sufficient   pam_u2f.so cue
@include common-auth

Where to implement

Login

For Ubuntu 17.10 and newer

sudo nano /etc/pam.d/gdm-password

Ubuntu 17.04 and older

sudo nano /etc/pam.d/lightdm

sudo

sudo nano /etc/pam.d/sudo

GNOME Authentication popup

sudo nano /etc/pam.d/polkit-1

TTY

sudo nano /etc/pam.d/login

Additional security

sudo timeout

If you want the sudo authentication prompt every time you run sudo.

sudo visudo

Apply ,timestamp_timeout=0 to the end of Defaults env_reset
Meaning that you will replace

Defaults        env_reset

with

Defaults        env_reset,timestamp_timeout=0

Lock the computer when the Yubikey is removed

Get the vendor and model ID of your Yubikey. Connect your Yubikey and run

udevadm monitor --environment --udev | grep 'ID_VENDOR_ID\|ID_MODEL_ID'

Now disconect your key and you should see something like this

ID_VENDOR_ID=1050
ID_MODEL_ID=0407

Create udev rules

sudo nano /etc/udev/rules.d/85-yubikey.rules

Paste this and replace the vendor and model ID with the ones you got in the previous step.

# Yubikey Udev Rule: running a bash script in case your Yubikey is removed 
ACTION=="remove", ENV{ID_VENDOR_ID}=="1050", ENV{ID_MODEL_ID}=="0407", RUN+="/usr/local/bin/gnome-screensaver-lock"

Now create a new file

sudo nano /usr/local/bin/gnome-screensaver-lock

And add this. Replace USERNAME with your actual username.

#!/bin/bash 
# Double checking if the Yubikey is actually removed
if [ -z "$(lsusb | grep Yubico)" ]
then
        logger "YubiKey Removed or Changed"
        sessionids=`/bin/loginctl list-sessions | grep USERNAME | awk '{print $1}'`
        for id in $sessionids
                do
                        logger "Locking session id:" $id
                        /bin/loginctl lock-session $id
                done
fi

Make the script executable

sudo chmod +x /usr/local/bin/gnome-screensaver-lock

Reload the udev rules

sudo udevadm control --reload-rules
sudo service udev reload

Access to the u2f_keys file

To secure this even further we can move the u2f_keys file to a part of the filesystem where you can't access it without root.

Create the directory.

sudo mkdir /etc/Yubico

Move the config.

sudo mv  ~/.config/Yubico/u2f_keys /etc/Yubico/u2f_keys

NOTE: After this is done you can't modify the file without your key. If you lose your key you're locked out. Always use two or more Yubikeys to prevent lockout.
This is also a bad idea if you have an encrypted /home directory since root wound be able to read it.

Add authfile=/etc/Yubico/u2f_keys to the end of every pam_u2f.so line.
Meaning that you will replace

auth    required   pam_u2f.so cue

with

auth    required   pam_u2f.so authfile=/etc/Yubico/u2f_keys cue

LUKS

You can use your Yubikey to unlock LUKS at boot. This requires you to already have an encrypted disk which you unlock with a password when your computer starts.

Install Yubikey LUKS

sudo apt install yubikey-luks

Backing up your LUKS headers

Before we start, let's backup the LUKS headers. Make sure to change the path to something that exists and copy the backup to an USB stick or anywhere else that's not the encrypted drive.

sudo cryptsetup luksHeaderBackup /dev/nvme0n1p3 --header-backup-file /path/to/backup/${HOSTNAME}-LUKS-header.backup-$(date -u +%Y-%m-%d_%H-%M-%S)

Find the name of your encrypted partition.

lsblk | grep crypt
Mine is shown as nvme0n1p3_crypt so we will use /dev/nvme0n1p3

Now we want to use an unused key slot for the Yubikeys. If you only use a single password to unlock your disk it will probably use just slot 0.

sudo cryptsetup luksDump /dev/nvme0n1p3