Using U2F at Linux Login
FIDO is the next big thing in multi factor authentication. Here is how I started using it to login my personal Linux computer.
VERY IMPORTANT: You are going to change a very critical system file (/etc/pam.d/common-auth) in this tutorial. If anything goes wrong, you may not be able to login to your computer anymore. Test what you are doing first in another system. No liability is assumed.
23.07.2018: I have updated the steps in this tutorial for a clean Ubuntu 18.04 installation on a linux container and to use libpam version 1.0.7.
- a Linux computer. I am using Ubuntu 18.04 LTS. In your distro, there might be differences on the locations of files. For this tutorial, I have installed a clean Ubuntu 18.04 on a linux container.
- a FIDO U2F device. I am using a Yubico Security Key.
Linux uses PAM (Pluggable Authentication Modules) to handle all authentication tasks. Since I am going to modify how I login (authenticate) to the system, using FIDO U2F, I need a PAM module providing this functionality.
$ apt-cache policy libpam-u2f libpam-u2f: Installed: (none) Candidate: 1.0.4-2 Version table: 1.0.4-2 500 500 http://de.archive.ubuntu.com/ubuntu bionic/universe amd64 Packages
libpam-u2f package is what I need. However, version 1.0.4 is released in 2016, and I really need some of the patches done after that, so I will use the latest version, which is 1.0.7 at the moment (23.07.2018), and build it from the source.
$ git clone https://github.com/Yubico/pam-u2f $ cd pam-u2f $ git tag pam_u2f-0.0.0 pam_u2f-0.0.1 pam_u2f-1.0.0 pam_u2f-1.0.1 pam_u2f-1.0.2 pam_u2f-1.0.3 pam_u2f-1.0.4 pam_u2f-1.0.5 pam_u2f-1.0.6 pam_u2f-1.0.7 $ git checkout pam_u2f-1.0.7
The build instructions are given in the project’s github page. Following them (and before that I do an update & upgrade):
$ sudo apt-get update $ sudo apt-get upgrade $ sudo apt-get install autoconf automake libtool libpam-dev asciidoc xsltproc libxml2-utils docbook-xml --no-install-recommends $ autoreconf --install $ apt-get install autoconf automake libtool pkg-config libu2f-host-dev libu2f-server-dev --no-install-recommends
The instructions says we can configure and make now but this gives an error and I think we need to run autoreconf again, so:
$ autoreconf --install $ ./configure $ make
This should end without any error. Then we can install it:
$ sudo make install
The library is (by default) installed here:
$ file /lib/x86_64-linux-gnu/security/pam_u2f.so /lib/x86_64-linux-gnu/security/pam_u2f.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=794a9f39069902d65f48f1f369496731570bdaa5, with debug_info, not stripped
Create a Backup User
Before using the PAM library, I create a new user in sudo group, with a very long/complex password and keep this in a secure place. I will not use this user normally, but keep it as a backup in case U2F authentication fails or the U2F device is broken or lost.
$ sudo adduser <backup_user> $ sudo usermod -aG sudo <backup_user>
Register a U2F Token
I will use the
pamu2fcfg tool that is built together with
pam_u2f.so above. The syntax is like below, all arguments are optional:
$ pamu2fcfg -uusername -opam://myorigin -ipam://myappid
I run this with the same user, so I omit -u, and I explicitly specify the origin and appid rather than using the default ones, so:
$ pamu2fcfg -opam://mydesktop -ipam://mydesktop
This will output a configuration line which I need and after running this the U2F device will blink and I touch it to complete the registration. I actually redirect it directly to the config file:
$ cd ~ $ mkdir .config/Yubico $ pamu2fcfg -opam://mydesktop -ipam://mydesktop > .config/Yubico/u2f_keys
This path is the default path
pam_u2f.so will look for each user.
I add the following line to the end of
auth sufficient pam_u2f.so debug cue nouserok origin=pam://mydesktop appid=pam://mydesktop
Since I set the origin and appid when using
pamu2fcfg, I also use origin and appid parameters here.
This configuration will make use of U2F device, if
$HOME/.config/Yubico/u2f_keys file is present, and if it is not present (or invalid) authentication will succeed (nouserok parameter). If you use the 1.0.4 version, this is not going to work, so make sure you use the latest version of
pam_u2f. Parameter cue prompts a message to remind to touch U2F device.
Very Important: The
u2f_keys file should not be under an encrypted file system, because files can be decrypted only after a successful authentication which requires
It is also possible to use a single system wide configuration (single
u2f_keys file) rather than using per-user
u2f_keys file using the authfile parameter of
I configured my user with
u2f_keys file, and the admin user without. At this point, I try if authenticating as the U2F configured user asks for the U2F device, and I can successfully authenticate using U2F, and also authenticating with the admin user does not ask for it. For example (and my u2f user is mete, admin user is paula):
Note: when you have debug in
pam_u2f.soconfiguration line in
common-auth, you will see some debug output as well. Below, I omit that output.
$ sudo ls [sudo] password for mete: <type password> Please touch the device. <the U2F device should be blinking now> <touch the U2F device> ... you will see file listing ...
If I try the same with the admin user:
$ su - paula [sudo] password for mete: <type password> ... you will see file listing ...
So it seems like the setup is working.
I actually tried not only sudo, but normal login and lock screen as well.
As everything is working as expected, I modify the U2F config in
common-auth and change sufficient to required and remove the debug parameter.
auth required pam_u2f.so cue nouserok origin=pam://mydesktop appid=pam://mydesktop
Since it is “required” now,
pam_u2f will succeed when:
- there is no U2F registration (no
u2f_keysfile) for the user trying to authenticate (nouserok parameter).
- there is a U2F registration given under
$HOME/.config/Yubico/u2f_keysof the user trying to authenticate and U2F device is plugged, touched and U2F authentication process completes successfully.
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.