2FA Login on Ubuntu with U2F and Google Authenticator

Note: This article infers that you have already configured a U2F device (like a Yubikey), and Google Authenticator. Also, when running pamu2fcfg, run it with the -P option.

Update: It turns out that repository package of pam-u2f version 1.0.8 didn’t support the userpresence=0 option necessary to disable the request for pressing the tactile trigger twice; this option is only supported by FIDO2-capable devices, which was clarified in this GitHub issue by the very knowledgeable (and patient) Alessio Di Mauro.

I’ve been interested in creating a similar authentication flow for my computers to the one we usually encounter on several popular websites (depicted in this Stack Exchange answer). This mainly consists of the following steps:

  • Enter username & password to authenticate
  • If available, use a U2F device as the second factor authentication (like Yubico’s Yubikey)
  • Otherwise, ask for a verification code (from, for example, Google Authenticator)

At first, I wanted to implement my own PAM module, but I’m still not confident enough to not shoot myself in the foot; then I tried my hand at cobbling something together with the pam_exec.so module, but realized that it wasn’t able to pass user input to a script, and in turn making it impossible to make use of the success=n action.

After reading a lot of documentation, I was able to put together something useful, without the need for extra dependencies (other than libpam-u2f, and libpam-google-authenticator).

# What the following lines accomplish:
#   Prompt for a U2F device, and to then press ENTER.
#   In case the U2F device is known, prompt the user to press the tactile trigger.
#   In case the U2F device is not know or present, prompt for a verification code from Google Authenticator.
#   Allow users that are not configured to use U2F or Google Authenticator to log in.
auth [success=1 new_authtok_reqd=ok ignore=ignore default=ignore] pam_u2f.so interactive userpresence=0 nouserok authfile=/etc/Yubico/u2f_keys
auth [success=1 new_authtok_reqd=ok ignore=ignore default=bad]    pam_google_authenticator.so nullok
auth required                                                     pam_u2f.so cue userpresence=1 nouserok authfile=/etc/Yubico/u2f_keys

Sources:

Note: As it was mentioned in the Update above, the desired behaviour would only be achieved with a modern FIDO2-capable device (as was discussed in this GitHub issue). However, for backwards compatibility with devices that don’t support U2F 1.2, I’ve included a version of the code that would require a double touch of the tactile trigger., but still work as intended.

# What the following lines accomplish:
#   Prompt for a U2F device, and to then press ENTER.
#   In case the U2F device is known, prompt the user to press the tactile trigger (twice).
#   In case the U2F device is not know or present, prompt for a verification code from Google Authenticator.
#   Allow users that are not configured to use U2F or Google Authenticator to log in.
auth [success=1 new_authtok_reqd=ok ignore=ignore default=ignore] pam_u2f.so interactive cue nouserok authfile=/etc/Yubico/u2f_keys
auth [success=1 new_authtok_reqd=ok ignore=ignore default=bad]    pam_google_authenticator.so nullok
auth required                                                     pam_u2f.so cue nouserok authfile=/etc/Yubico/u2f_keys

Multiple PNGs to PDF in Command-Line

Note: Keep in mind that this was written during the Covid-19 Pandemic.

So, I found myself having to send a signed and scanned document… but paranoid enough to not want to break quarantine to print, sign, and scan a document; I was also doubting that I could simply overlay a copy-pasted signature (because it’s probable that older generations want the document to ‘seem’ that it was scanned).

Long story short… I wanted to create a print-less scan-less signed and scanned document.

Long story long… I went through a lengthy process that consisted of roughly:

  • converting PDF to PNG
  • adding paper background texture; and whitening (scanners seem to perform some image processing to improve contrast)
  • manually signing with GIMP’s ink tool the date and signature for each page
  • applying GIMP’s Photocopy effect to make the document seem printed
  • slightly rotating each layer to make the document seem that it had some alignment issues
  • adding fake scanned frame (paper edges and shadow) from another document I had previously scanned

The only limitation was that the largest paper background texture I found was only 1600×1200 px in size, so my images were a bit small for an A4 document; this allowed for a 136 ppi (around 53.5 dot/cm) A4 document..

Once all that was done,  I had to convert the several png images into a single pdf. On my first attempt, after reading the documentation on ImageMagick’s Convert and its convert command-line options, I was trying to do the conversion as follows:

convert -verbose \
    -units PixelsPerInch \
    -page A4 \
    -density 136x136 \
    -size 1123x1590 \
    -resample 136 \
    *.png \
    output.pdf

But I was obtaining a document with a reduced size (a B9 document in paper size according to Ubuntu’s Document Viewer, evince). After reading this discussion in the ImageMagick Forum, there seemed to be a 13-year-old bug that was still causing problems. The fix turned out to be:

convert -verbose \
    *.png \
    -resize 1123x1590 \
    -units 'PixelsPerInch' \
    -density 136x136 \
    output.pdf

That worked like a charm.