Linux Mint 21/22 Cinnamon: FIDO2 + PIN Login Walkthrough

A practical, recovery-conscious guide for FIDO2 PIN + touch login on Linux Mint Cinnamon using pam_u2f, a group-gated policy, a central mapping file, LightDM, sudo, optional su, and Cinnamon screen unlock.

Revision: Mint Cinnamon v1.0, derived from the Debian XFCE v4.4 lab. Greeter-based locking is treated as required for FIDO-only desktop use; token-removal behavior switches to the LightDM greeter; keyring handling and rollback cleanup are included.

Linux Mint 21.x / 22.xCinnamon + LightDMFIDO2 PIN + touchbreakglass password account preserved
Edition-specific, not yet validated on Mint. This guide is derived from the Debian 13.5 / XFCE v4.4 lab, which was tested on that platform. The FIDO2/PAM core (sections 5–15, 19–21) is desktop-agnostic and carries over directly. The desktop-integration steps that differ on Cinnamon — the screen locker, the lock keybinding, and idle behavior (sections 12, 16, 17, 18) — are marked verify on your install and must be confirmed on your actual Mint Cinnamon VM before classroom use. See the consolidated verification list at the end of section 18.
Contents
  1. What are FIDO U2F and FIDO2?
  2. Authentication design used by this guide
  3. Assumptions, placeholders, and safety preconditions
  4. Command style in this guide
  5. Install required packages
  6. Set or verify the FIDO2 PIN
  7. Pre-PAM FIDO2/PIN test
  8. Create and populate the FIDO login group
  9. Create the central PAM mapping file
  10. Create a shared PAM include file
  11. Test PAM with a standalone service
  12. Configure LightDM graphical login
  13. Configure sudo
  14. Core FIDO login checkpoint
  15. Configure su, optional
  16. Configure Cinnamon lock behavior: use the LightDM greeter, not the raw screen locker
  17. Switch to the LightDM greeter when the FIDO key is removed
  18. Extended test matrix before reboot
  19. Disable Unix password login for FIDO users
  20. Optional: GNOME Keyring and Chrome/Chromium prompts
  21. Emergency rollback
  22. Option notes and policy choices
  23. References and source notes

1. What are FIDO U2F and FIDO2?

FIDO U2F and FIDO2 are authentication standards from the FIDO Alliance that use public-key cryptography instead of reusable shared secrets. The private credential remains on the authenticator, such as a hardware security key, while the relying system stores only public registration data.

FIDO U2F

FIDO U2F, or Universal 2nd Factor, is the older model. It is primarily used as a second factor: the user enters a normal password first, then proves possession of the hardware token by touching or activating it.

FIDO2

FIDO2 is the newer model. It supports stronger authenticator behavior, including PIN-backed and potentially passwordless authentication. Depending on the token and software stack, FIDO2 can support a flow where the security key effectively replaces the account password.

FeatureFIDO U2FFIDO2
Common useSecond factor after a passwordPasswordless or strong hardware-backed login
Typical user flowPassword + token touchToken PIN and/or biometric + token touch
Protocol familyCTAP1 / U2FCTAP2 and WebAuthn
Linux PAM use in this guideNot the preferred targetFIDO2 PIN + physical touch for selected users
Important distinction: WebAuthn/FIDO2 phishing resistance is strongest in web authentication because the credential is bound to a specific relying-party origin. This walkthrough is about local Linux PAM login, not website login. The local benefit is hardware-backed, PIN-protected, touch-confirmed authentication for selected local accounts.

2. Authentication design used by this guide

This guide uses a group-gated local policy:

  • Users in fido-login authenticate with FIDO2 token PIN + physical touch only.
  • Users not in fido-login, such as a controlled breakglass/local-admin account, remain password-only.
  • FIDO users do not fall back to Unix password if FIDO fails.
Shared PAM policy snippet
auth [success=ignore default=1] pam_succeed_if.so quiet user ingroup fido-login
auth [success=done default=die] pam_u2f.so authfile=/etc/security/u2f_keys cue="FIDO users: enter token PIN, then touch token when it flashes" pinverification=1 userverification=0
Do not use sufficient with nouserok. That combination can accidentally allow unmapped users to bypass password authentication. This guide avoids that pattern.

3. Assumptions, placeholders, and safety preconditions

Replace these placeholders before running commands:

PlaceholderMeaning
FIDO_USERThe normal local user who will use the FIDO token.
BREAKGLASS_USERA separate, known-working, sudo-capable local account that remains password-only.
/dev/hidraw1The FIDO token device path shown by fido2-token -L. The number may differ on your system (hidraw0, hidraw2, etc.) depending on other HID devices present — always confirm with fido2-token -L rather than assuming hidraw1.
Do not proceed with PAM changes using your only sudo-capable account. Create and test a separate password-only sudo-capable local account first. Confirm it can log in and run sudo -v. Keep that account out of fido-login.
  • Keep a root-capable terminal or TTY recovery path available while testing.
  • Do not modify /etc/pam.d/login in this walkthrough. Console TTY password login is your recovery path.
  • Back up each PAM file before editing it. The commands below include backup steps.
  • Do not close your working session until LightDM, sudo, and screen unlock have all been tested.

4. Command style in this guide

Command blocks are copy-pasteable and do not include shell prompt characters. The label above each block tells you whether it is intended for a normal user shell, a sudo command, or a PAM snippet.

VirtualBox: enable USB passthrough for the FIDO token

If you are running Linux Mint inside VirtualBox, the FIDO token must be explicitly passed through to the VM before the guest OS can see it. VirtualBox does not pass USB devices to a VM by default.

Do this before proceeding to section 5. Without a USB filter, commands like fido2-token -L will return no devices even if the token is physically inserted.
  1. With the VM powered off, open VirtualBox Manager and select your VM.
  2. Click Settings → USB.
  3. Make sure Enable USB Controller is checked. Choose USB 2.0 (EHCI) or USB 3.0 (xHCI) depending on your host and token. The xHCI controller requires the VirtualBox Extension Pack.
  4. Click the Add USB filter icon (plug with a green plus). Insert the FIDO token into the host first so it appears in the device list, then select it. This creates a filter that automatically routes that token to the VM whenever it is inserted.
  5. Click OK and start the VM.
  6. Once booted, insert the FIDO token and verify the guest sees it: Normal user shell
    lsusb
    fido2-token -L
    fido2-token -L should list a device path such as /dev/hidraw1: vendor model FIDO+U2F. If it returns nothing, confirm the USB filter is saved and the correct controller type is selected.
USB controller type: if the token still does not appear after adding the filter, try switching between USB 2.0 and USB 3.0 in the VM USB settings. Some tokens enumerate differently depending on the host port and controller.

5. Install required packages

Uses sudo
sudo apt update
sudo apt install libpam-u2f pamu2fcfg fido2-tools pamtester
Mint base and package versions (Mint 21 vs 22). Linux Mint's main editions are built on an Ubuntu LTS base, not Debian: Mint 21.x = Ubuntu 22.04, Mint 22.x = Ubuntu 24.04. The package names above are identical, but two version-sensitive points matter:

1. pam_u2f PIN support. This guide uses pinverification=1 (section 9), which needs libpam-u2f ≥ 1.1.0. Mint 22 is comfortably current. On Mint 21 it is near the floor, so confirm the installed version before relying on it:
dpkg -l libpam-u2f | tail -n1
If the version is older than 1.1.0, the pinverification option will be ignored or error; enable the backports repository or upgrade to Mint 22.

2. common-auth shape. The Ubuntu-base /etc/pam.d/common-auth differs slightly from Debian's, but this guide never edits common-auth directly — it inserts @include fido2-local-auth above the existing @include common-auth line in each service (sections 12, 13), so the strategy holds on both bases.

6. Set or verify the FIDO2 PIN

Normal user shell
fido2-token -L

Example output:

/dev/hidraw1: KEY-ID FIDO+U2F
Normal user shell
fido2-token -I /dev/hidraw1

Set a PIN if needed:

Normal user shell
fido2-token -S /dev/hidraw1

Change an existing PIN if needed:

Normal user shell
fido2-token -C /dev/hidraw1
Brand-new or unverified token? Instructors have an acceptance-test helper, fido-token-test.sh, that detects a key, dumps its identity, and runs a live touch/crypto round-trip before you enroll it. Ask your instructor to vet a new token first — the tool and its safe reset/identity features live in the Instructor Reference, not this walkthrough.

7. Pre-PAM FIDO2/PIN test

Before touching PAM, verify that the token accepts its PIN and requires physical presence.

Normal user shell
rm -rf /tmp/fido2-login-test
mkdir -p /tmp/fido2-login-test
cd /tmp/fido2-login-test
Normal user shell
echo "debian local login test challenge" | openssl sha256 -binary | base64 > cred_param
echo "localhost" >> cred_param
echo FIDO_USER >> cred_param
dd if=/dev/urandom bs=32 count=1 status=none | base64 >> cred_param
Normal user shell
fido2-cred -M -t pin=true -i cred_param /dev/hidraw1 | fido2-cred -V -o cred

Expected behavior for a KEY-ID FIDO+U2F style token: enter the FIDO2 PIN, watch for the LED/button to flash, then press the token button. The command should return successfully and create cred.

Normal user shell
ls -l cred
cat cred

If you intentionally enter a bad PIN, FIDO_ERR_PIN_INVALID is expected. If you run without -t pin=true and see FIDO_ERR_PIN_REQUIRED, rerun with -t pin=true.

Normal user shell
cd
rm -rf /tmp/fido2-login-test

8. Create and populate the FIDO login group

The fido-login group is the selector. Members use FIDO2; non-members use password auth.

Uses sudo
sudo groupadd --force fido-login
sudo usermod -aG fido-login FIDO_USER
id FIDO_USER
getent group fido-login
Log out and back in, or reboot, after adding the user to the group. Existing graphical sessions may not have the new supplemental group until a new login session starts.

9. Create the central PAM mapping file

Use a central mapping file instead of ~/.config/Yubico/u2f_keys. This avoids encrypted-home and graphical-locker timing problems.

Normal user shell
pamu2fcfg -N -u FIDO_USER > /tmp/u2f_keys-FIDO_USER
cat /tmp/u2f_keys-FIDO_USER

Expected: token PIN prompt, optional flashing/touch, and one mapping line beginning with FIDO_USER:.

Uses sudo
sudo install -o root -g fido-login -m 0640 /tmp/u2f_keys-FIDO_USER /etc/security/u2f_keys
rm -f /tmp/u2f_keys-FIDO_USER
sudo python3 -c 'from pathlib import Path; p=Path("/etc/security/u2f_keys"); p.write_text(p.read_text().rstrip()+"\n")'
sudo ls -l /etc/security/u2f_keys
sudo grep "^FIDO_USER:" /etc/security/u2f_keys

Expected permissions:

-rw-r----- 1 root fido-login ... /etc/security/u2f_keys
Why 0640 root:fido-login? Some graphical unlockers run PAM in the user’s session context, not as root. A root-only 0600 mapping file can work under sudo pamtester but fail during actual screen unlock. The mapping file contains public credential registration data, not the token private key, so group-readable by fido-login is appropriate for this design.

Enroll a backup token

Insert the backup token, then append a second credential to the same user line.

Uses sudo and normal user commands
sudo cp /etc/security/u2f_keys /tmp/u2f_keys-FIDO_USER.new
sudo chown FIDO_USER:fido-login /tmp/u2f_keys-FIDO_USER.new
chmod 0640 /tmp/u2f_keys-FIDO_USER.new
printf ':' >> /tmp/u2f_keys-FIDO_USER.new
pamu2fcfg -N -n >> /tmp/u2f_keys-FIDO_USER.new
sudo install -o root -g fido-login -m 0640 /tmp/u2f_keys-FIDO_USER.new /etc/security/u2f_keys
rm -f /tmp/u2f_keys-FIDO_USER.new
sudo python3 -c 'from pathlib import Path; p=Path("/etc/security/u2f_keys"); p.write_text(p.read_text().rstrip()+"\n")'
sudo ls -l /etc/security/u2f_keys

10. Create a shared PAM include file

Instead of copying the same FIDO logic into every PAM service, put it in one reusable include file.

Control-flow note: This file intentionally uses success=done. Use PAM include/@include, not substack, so successful FIDO authentication stops before password auth.
Backup if file exists, then write file
sudo test -e /etc/pam.d/fido2-local-auth && sudo cp -a /etc/pam.d/fido2-local-auth /etc/pam.d/fido2-local-auth.bak || true
sudo tee /etc/pam.d/fido2-local-auth >/dev/null <<'EOF'
{{EMBED:config/fido2-local-auth}}
EOF

Use one of these include styles depending on the surrounding PAM file:

Debian/Ubuntu @include style
@include fido2-local-auth
@include common-auth
Typed auth include style
auth include fido2-local-auth
auth include common-auth

11. Test PAM with a standalone service

Create a temporary PAM service before editing LightDM, sudo, su, or screen-locker files.

Backup if file exists, then write test service
sudo test -e /etc/pam.d/fido2-test && sudo cp -a /etc/pam.d/fido2-test /etc/pam.d/fido2-test.bak || true
sudo tee /etc/pam.d/fido2-test >/dev/null <<'EOF'
{{EMBED:config/fido2-test}}
EOF
Uses sudo
sudo pamtester fido2-test FIDO_USER authenticate
sudo pamtester fido2-test BREAKGLASS_USER authenticate

Expected: FIDO_USER gets FIDO PIN + touch only. BREAKGLASS_USER gets password only.

If pamtester says “Authentication service cannot retrieve authentication info”

Diagnostic commands
whoami
id FIDO_USER
getent group fido-login
sudo ls -l /etc/security/u2f_keys
sudo grep "^FIDO_USER:" /etc/security/u2f_keys
sudo cat /etc/pam.d/fido2-local-auth
sudo cat /etc/pam.d/fido2-test

12. Configure LightDM graphical login

Mint uses Slick Greeter, not the GTK greeter. All Mint editions default to slick-greeter (lightdm-slick-greeter) as the LightDM greeter, whereas the Debian XFCE lab this guide is derived from used lightdm-gtk-greeter. The PAM file you edit is the same — /etc/pam.d/lightdm — and the group-gated policy behaves identically. What differs is only how the greeter renders the FIDO PIN prompt and cue. The prompt-quirk guidance later in this section is written for Slick Greeter but has not been validated on Mint; confirm the actual on-screen behavior on your install. Check which greeter is active with:
cat /etc/lightdm/lightdm.conf.d/*.conf /etc/lightdm/lightdm.conf 2>/dev/null | grep -i greeter-session

Edit /etc/pam.d/lightdm, not /etc/pam.d/lightdm-greeter, for normal user login authentication.

Backup, then edit
sudo cp -a /etc/pam.d/lightdm /etc/pam.d/lightdm.bak
sudo editor /etc/pam.d/lightdm

Find the service’s existing password include, usually:

@include common-auth

Insert the shared FIDO include immediately above it. Preserve unrelated lines such as pam_nologin, pam_env, SELinux, limits, loginuid, and keyring lines.

PAM snippet
# FIDO2 local authentication policy
@include fido2-local-auth

@include common-auth

Do not modify lightdm-greeter on the first pass

/etc/pam.d/lightdm-greeter normally permits the greeter process itself to start. It is not the normal user-authentication path.

Typical greeter line
auth      required pam_permit.so

Optional: prefer username-first graphical login

The group-gated PAM design needs to know the username before it selects the FIDO or password path. LightDM supports manual username entry when the greeter supports it. The greeter-hide-users and greeter-show-manual-login settings below are LightDM seat settings, honored by Slick Greeter as well as the GTK greeter.

Uses sudo
sudo mkdir -p /etc/lightdm/lightdm.conf.d
sudo tee /etc/lightdm/lightdm.conf.d/50-manual-login.conf >/dev/null <<'EOF'
{{EMBED:config/50-manual-login.conf}}
EOF

Expected presentation:

Username:
Password/PIN:
Verify on your install: confirm Slick Greeter actually presents a manual username field after applying this. Some Slick Greeter builds need greeter-show-manual-login=true to take effect only after a full LightDM restart (sudo systemctl restart lightdm — do this only from a safe recovery position, not mid-configuration).

Pre-logout LightDM PAM test

Uses sudo
sudo pamtester lightdm FIDO_USER authenticate
sudo pamtester lightdm BREAKGLASS_USER authenticate

Slick Greeter prompt behavior

Verify on your install — not yet validated on Mint. On the GTK greeter (Debian XFCE), the greeter sometimes displays blank prompt lines for the FIDO/PAM conversation until Enter is pressed. Slick Greeter renders the PAM conversation differently, and its handling of a custom pam_u2f cue and PIN prompt has not been confirmed for this lab. When you test the greeter on Mint, note exactly what appears: whether the PIN prompt and the cue text (“FIDO users: enter token PIN, then touch token when it flashes”) are shown, whether you must press Enter first, and whether the token flashes on schedule. Record the observed flow so it can be documented for students.

Prompt behavior (Slick Greeter): if the greeter shows blank lines instead of a clear PIN/password prompt, try pressing Enter once, then enter the FIDO token PIN and touch the token when it flashes. Password-only users should still authenticate with their normal Unix password. Confirm this behavior on your Mint Cinnamon install before relying on it in class.

13. Configure sudo

Backup, then edit
sudo cp -a /etc/pam.d/sudo /etc/pam.d/sudo.bak
sudo editor /etc/pam.d/sudo

Place the shared FIDO include immediately before @include common-auth.

PAM snippet
session    required   pam_limits.so

@include fido2-local-auth
@include common-auth
@include common-account
@include common-session-noninteractive
Test
sudo -k
sudo -v
Warning: sudo package updates can overwrite /etc/pam.d/sudo. The sudo package owns /etc/pam.d/sudo as a dpkg conffile. Unattended or non-interactive upgrades — including unattended-upgrades, automated patching, or accepting a "replace modified conffile" prompt at an apt prompt — can silently replace your edited file with the package default, removing @include fido2-local-auth and disabling FIDO for sudo with no warning. Complete section 13.1 before proceeding.

13.1 Protect the sudo PAM configuration from package updates

Install an apt post-invoke hook that checks for the FIDO include after every apt invocation and re-adds it if a package upgrade removed it.

Step 1: Create the guard script.

Uses sudo
sudo tee /usr/local/sbin/fido2-sudo-pam-guard >/dev/null <<'EOF'
{{EMBED:scripts/fido2-sudo-pam-guard}}
EOF
sudo chmod 755 /usr/local/sbin/fido2-sudo-pam-guard

Step 2: Install the apt hook.

Uses sudo
sudo tee /etc/apt/apt.conf.d/99-fido2-sudo-pam-guard >/dev/null <<'EOF'
{{EMBED:config/99-fido2-sudo-pam-guard}}
EOF

Step 3: Verify the guard works before relying on it.

Test
# Confirm the include is present
sudo grep fido2-local-auth /etc/pam.d/sudo

# Simulate removal, run the guard, confirm it re-adds the line
sudo sed -i '/fido2-local-auth/d' /etc/pam.d/sudo
sudo /usr/local/sbin/fido2-sudo-pam-guard
sudo grep fido2-local-auth /etc/pam.d/sudo

# Confirm sudo still requires FIDO
sudo -k
sudo -v
How the hook works: After every apt invocation, the hook checks whether @include fido2-local-auth is present in /etc/pam.d/sudo. If a package upgrade removed it, the script re-inserts it immediately before @include common-auth and logs the event via logger. The hook is a no-op when the include is already present. Trade-off: if a future sudo upgrade restructures the file and removes @include common-auth as the marker, the re-insertion will silently fail — check /var/log/syslog for fido2-sudo-pam-guard entries after major upgrades.
If sudo is already broken after an upgrade: You can still run sudo using your password (the FIDO include is gone but common-auth falls back to password). Re-run the guard manually — sudo /usr/local/sbin/fido2-sudo-pam-guard — then confirm with sudo -k && sudo -v that FIDO is active again.
If your Unix password is also disabled (section 19), a sudo overwrite is a lockout. In later sections this guide locks the FIDO user's Unix password with passwd -l. If a package upgrade removes the FIDO include and the password is locked, common-auth has nothing to fall back to — the FIDO user cannot run sudo at all. Your only recovery path is the password-only breakglass account. This is exactly why the breakglass account must remain password-capable, must stay outside the fido-login group, and must never have its password locked.

14. Core FIDO login checkpoint

At this point, the core FIDO login design is complete only if the standalone PAM test, LightDM test, breakglass test, and real sudo -v test all pass.

Do not log out, reboot, or lock the FIDO user's Unix password yet. Keep a root-capable shell open until the greeter, sudo, breakglass login, and lock behavior have all been tested.
Core testCommand or actionExpected result
FIDO test servicesudo pamtester fido2-test FIDO_USER authenticateFIDO PIN + touch only.
Breakglass test servicesudo pamtester fido2-test BREAKGLASS_USER authenticatePassword only.
LightDM FIDO usersudo pamtester lightdm FIDO_USER authenticateFIDO PIN + touch only.
LightDM breakglass usersudo pamtester lightdm BREAKGLASS_USER authenticatePassword only.
Real sudo from FIDO sessionsudo -k, then sudo -vFIDO PIN + touch from the actual FIDO_USER session.

The remaining sections are desktop-integration and hardening steps: optional su, required greeter-based lock behavior, token-removal greeter switching, password locking, keyring behavior, and rollback.

15. Configure su, optional

This is optional. Preserve pam_rootok.so before the FIDO include so root-originated su keeps normal behavior.

Backup, then edit
sudo cp -a /etc/pam.d/su /etc/pam.d/su.bak
sudo editor /etc/pam.d/su

The important ordering is:

PAM snippet
auth       sufficient pam_rootok.so

@include fido2-local-auth
@include common-auth
Test
su - FIDO_USER
su - BREAKGLASS_USER

16. Configure Cinnamon lock behavior: use the LightDM greeter, not the raw screen locker

Not yet validated on Mint — verify on your install. This entire section is the Cinnamon adaptation of the XFCE lab's greeter-based lock design. The mechanism (drive lock to the LightDM greeter, keep the native locker PAM-valid as a fallback) is unchanged, but the Cinnamon-specific commands — the gsettings keybinding paths and the idle settings — must be confirmed on your actual Mint Cinnamon VM.

The in-process cinnamon-screensaver unlock dialog is not a good primary FIDO unlock surface: like the XFCE screensaver, it authenticates only the currently logged-in user, does not offer Switch User, and can flicker or loop when the token is absent. The design used here sends the user to the LightDM greeter for lock instead, which preserves Switch User and the password-only breakglass account.

Design rule: do not use the raw cinnamon-screensaver unlock dialog as the normal FIDO unlock path. Use the LightDM greeter for manual lock, switch-user behavior, and token-removal locking (section 17). Keep cinnamon-screensaver PAM-valid only as an idle-timeout fallback.

Keep the Cinnamon screensaver PAM file sane as a fallback

Even though the primary lock flow uses the LightDM greeter, keep /etc/pam.d/cinnamon-screensaver valid. This prevents confusing PAM errors if Cinnamon still invokes the screensaver dialog during idle timeout or other edge cases.

Uses sudo
sudo cp -a /etc/pam.d/cinnamon-screensaver /etc/pam.d/cinnamon-screensaver.bak.before-fido2-local-auth
sudo editor /etc/pam.d/cinnamon-screensaver

Use this content:

PAM snippet
#%PAM-1.0

auth include fido2-local-auth
auth include common-auth
auth optional pam_gnome_keyring.so

account required pam_permit.so

The explicit account required pam_permit.so line avoids the pam_unix(...:account): setuid failed account-management problem observed with the analogous XFCE screensaver service.

Test the PAM service directly:

Uses sudo
sudo pamtester cinnamon-screensaver FIDO_USER authenticate
sudo pamtester cinnamon-screensaver FIDO_USER acct_mgmt
sudo pamtester cinnamon-screensaver BREAKGLASS_USER authenticate
sudo pamtester cinnamon-screensaver BREAKGLASS_USER acct_mgmt
TestExpected result
FIDO_USER authenticateFIDO PIN + touch.
FIDO_USER acct_mgmtSuccess.
BREAKGLASS_USER authenticatePassword.
BREAKGLASS_USER acct_mgmtSuccess.

Make manual lock switch to the LightDM greeter

Cinnamon has no xflock4-style indirection and no /general/LockCommand setting. Its lock shortcut invokes cinnamon-screensaver directly. To route lock to the greeter instead, unbind the built-in lock shortcut and add a Cinnamon custom keybinding that runs dm-tool switch-to-greeter. Run these as FIDO_USER inside the graphical Cinnamon session — these are per-user gsettings, not sudo.

Normal graphical session (as FIDO_USER)
# 1. Unbind Cinnamon's built-in "lock screen" shortcut so it no longer
#    launches cinnamon-screensaver directly.
gsettings set org.cinnamon.desktop.keybindings.media-keys screensaver "[]"

# 2. Register one custom keybinding entry.
gsettings set org.cinnamon.desktop.keybindings custom-list "['custom0']"

# 3. Point that entry at the greeter-switch command, bound to Super+L.
BASE="org.cinnamon.desktop.keybindings.custom-keybinding:/org/cinnamon/desktop/keybindings/custom-keybindings/custom0/"
gsettings set "$BASE" name    "'Lock to LightDM greeter'"
gsettings set "$BASE" command "'dm-tool switch-to-greeter'"
gsettings set "$BASE" binding "['<Super>l']"

Verify the settings were written:

Normal graphical session (as FIDO_USER)
gsettings get org.cinnamon.desktop.keybindings custom-list
gsettings get "$BASE" command
gsettings get "$BASE" binding

Test manual locking by pressing Super+L, or by running the command the keybinding invokes directly from the session terminal:

Normal graphical session (as FIDO_USER)
dm-tool switch-to-greeter

Expected behavior:

  • The machine switches to the LightDM greeter instead of the cinnamon-screensaver unlock dialog.
  • The FIDO user authenticates through LightDM with FIDO PIN + touch.
  • The breakglass user remains available with normal password authentication.
  • Switch-user behavior remains available at the greeter.
Verify on your install: confirm that (a) Cinnamon actually fires the custom0 keybinding on Super+L — custom-keybinding reliability varies between Cinnamon versions — and (b) the built-in shortcut no longer also triggers cinnamon-screensaver. If Super+L still raises the native locker, check that org.cinnamon.desktop.keybindings.media-keys screensaver is empty and that no other schema (for example a hardware XF86ScreenSaver key) is bound to it.

If dm-tool switch-to-greeter fails from a terminal

The greeter switch needs the graphical session environment: DISPLAY, XDG_RUNTIME_DIR, and DBUS_SESSION_BUS_ADDRESS. A nested login shell such as su - FIDO_USER may strip those variables.

Normal graphical session (as FIDO_USER)
echo "$DISPLAY"
echo "$XDG_RUNTIME_DIR"
echo "$DBUS_SESSION_BUS_ADDRESS"

If these are empty, exit the nested login shell and test from the original Cinnamon terminal session. (The token-removal helper in section 17 does not have this limitation — it reconstructs the session environment from loginctl.)

Idle-timeout locking on Cinnamon

Cinnamon cannot run an arbitrary command on idle the way a configurable locker can, so there is no clean way to make idle timeout switch to the greeter. You must choose one of two idle postures, and test the one you pick before considering the setup complete:

  1. Disable native idle locking and rely on manual lock (Super+L → greeter) and token removal (section 17) as the lock triggers. The screen may still blank on idle, but it will not auto-lock — acceptable only where physical access is otherwise controlled. Normal graphical session (as FIDO_USER)
    gsettings set org.cinnamon.desktop.screensaver lock-enabled false
    gsettings set org.cinnamon.desktop.session idle-delay 0
  2. Keep native idle locking via cinnamon-screensaver, accepting that an idle lock lands on the in-process FIDO unlock dialog (which you kept PAM-valid above) rather than the greeter. The FIDO PIN + touch flow still works, but Switch User and breakglass are not available from that dialog until the token is reinserted.

Check which lockers are running:

Normal graphical session
pgrep -a 'cinnamon-screensaver|light-locker|xscreensaver|xsecurelock'

17. Switch to the LightDM greeter when the FIDO key is removed

This section sends the machine to the LightDM greeter when the FIDO token is removed. It depends on the greeter-based lock behavior configured and tested in the previous section. This is part of the intended desktop behavior for this FIDO-only setup, but it is still not an authentication control; the real authentication control remains the FIDO/PAM login policy.

Design intent: for this Cinnamon/LightDM setup, token removal should switch to the LightDM greeter rather than invoking cinnamon-screensaver-command --lock or forcing the cinnamon-screensaver unlock dialog. The greeter path preserves access to user switching and the password-only breakglass account. The helper and udev rule below are the DE-agnostic pieces reused verbatim from the XFCE lab; they were tested there, but the end-to-end token-removal flow has not yet been validated on Mint Cinnamon — confirm it on your install.
Why not just call cinnamon-screensaver-command --lock? Locking into the in-process cinnamon-screensaver dialog on token removal can trap the user inside the current session's FIDO-only unlock dialog. If the token is absent, the unlock dialog may flicker or repeatedly restart, and the Switch User path may not be available until the token is reinserted. Switching to the LightDM greeter avoids that failure mode.

17.1. Confirm the greeter switch command exists

Normal graphical session
command -v dm-tool

Expected result:

Example output
/usr/bin/dm-tool

From the real Cinnamon terminal session, test switching to the greeter:

Normal graphical session
dm-tool switch-to-greeter

Expected behavior: the session switches to the LightDM greeter. From there, the FIDO user should be able to authenticate with FIDO PIN + touch, and the breakglass user should be able to authenticate with a normal password.

Greeter prompt behavior (Slick Greeter): Mint's Slick Greeter renders the FIDO/PAM conversation differently from the GTK greeter. If no prompt text is visible, try pressing Enter once; the FIDO prompt should then appear. Enter the token PIN, then touch the token when it flashes. Confirm this on your install — see section 12.

17.2. Find the token's udev identifiers

Insert the FIDO key, then monitor udev events:

Uses sudo
sudo udevadm monitor --udev --environment

Remove the FIDO key and look for the hidraw remove event. Prefer the event that includes ID_FIDO_TOKEN=1 and ID_SECURITY_TOKEN=1.

Example remove event
ACTION=remove
SUBSYSTEM=hidraw
DEVNAME=/dev/hidraw1
ID_FIDO_TOKEN=1
ID_SECURITY_TOKEN=1
ID_VENDOR_ID=096e
ID_MODEL_ID=0858
ID_MODEL=FIDO

Record ID_VENDOR_ID and ID_MODEL_ID. If your token exposes a truly unique serial number, you may also match on that, but some tokens expose a generic product serial string rather than a per-token serial.

17.3. Create the greeter-switch helper

This helper is run by root through udev/systemd, finds the active local graphical session, reconstructs the session environment, and runs dm-tool switch-to-greeter as the graphical user.

Uses sudo
sudo tee /usr/local/sbin/fido-remove-switch-to-greeter >/dev/null <<'EOF'
{{EMBED:scripts/fido-remove-switch-to-greeter}}
EOF

sudo chown root:root /usr/local/sbin/fido-remove-switch-to-greeter
sudo chmod 0755 /usr/local/sbin/fido-remove-switch-to-greeter

17.4. Test the helper manually

Uses sudo
sudo /usr/local/sbin/fido-remove-switch-to-greeter

Expected behavior: the session switches to the LightDM greeter. After returning, inspect logs:

Troubleshooting
sudo journalctl -b --since "3 minutes ago" | grep -Ei 'fido-switch-greeter|dm-tool|lightdm|greeter'

If dm-tool reports Not running inside a display manager, XDG_SEAT_PATH not defined, verify that the helper includes the XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0 environment variable.

17.5. Test a logging-only udev rule first

Before letting udev switch the greeter, confirm the rule fires on the correct remove event. Replace the vendor/model IDs with the values observed from your token.

Uses sudo
sudo tee /etc/udev/rules.d/85-fido-lock-on-remove-test.rules >/dev/null <<'EOF'
{{EMBED:config/85-fido-lock-on-remove-test.rules}}
EOF

sudo udevadm control --reload-rules

Remove the token, then check for the test log:

Troubleshooting
sudo journalctl -b --since "2 minutes ago" | grep -i fido-udev-test

If the test log appears, remove the test rule:

Uses sudo
sudo rm -f /etc/udev/rules.d/85-fido-lock-on-remove-test.rules
sudo udevadm control --reload-rules

17.6. Create the real udev removal rule

Do not run dm-tool directly from udev. udev jobs should be short-lived. Use systemd-run --no-block to hand the work off to systemd.

Uses sudo
sudo tee /etc/udev/rules.d/85-fido-lock-on-remove.rules >/dev/null <<'EOF'
{{EMBED:config/85-fido-lock-on-remove.rules}}
EOF

sudo udevadm control --reload-rules

17.7. Test token removal

  1. Stay logged into Cinnamon.
  2. Insert the FIDO key.
  3. Remove the FIDO key.
  4. The machine should switch to the LightDM greeter.
  5. Select the FIDO user and reinsert the token to authenticate with FIDO PIN + touch, or select the password-only breakglass user.

Check logs after the test:

Troubleshooting
sudo journalctl -b --since "3 minutes ago" | grep -Ei 'fido-switch-greeter|fido-udev|udev|dm-tool|lightdm|greeter'

17.8. Notes on testing the greeter switch by hand

Running dm-tool switch-to-greeter by hand only works from the original graphical Cinnamon session environment. It needs DISPLAY, XDG_RUNTIME_DIR, and DBUS_SESSION_BUS_ADDRESS. If those variables are empty, such as inside a nested su - login shell, the manual command may fail even though the desktop session is healthy.

Graphical user session
echo "$DISPLAY"
echo "$XDG_RUNTIME_DIR"
echo "$DBUS_SESSION_BUS_ADDRESS"

The greeter-switch helper does not depend on the current shell environment; it reconstructs the graphical session environment from loginctl.

17.9. Rollback the removal-switch feature (optional)

Only perform this rollback if you do not need the token-removal locking feature. Section 18 uses FIDO key removal as one of the extended test matrix items. Do not roll back this feature before completing that test.
Uses sudo
sudo rm -f /etc/udev/rules.d/85-fido-lock-on-remove.rules
sudo rm -f /etc/udev/rules.d/85-fido-lock-on-remove-test.rules
sudo rm -f /usr/local/sbin/fido-remove-switch-to-greeter
sudo udevadm control --reload-rules

18. Extended test matrix before reboot

TestCommand or actionExpected result
FIDO test servicesudo pamtester fido2-test FIDO_USER authenticateFIDO PIN + touch only.
Breakglass test servicesudo pamtester fido2-test BREAKGLASS_USER authenticatePassword only.
LightDM FIDO usersudo pamtester lightdm FIDO_USER authenticateFIDO PIN + touch only.
LightDM breakglass usersudo pamtester lightdm BREAKGLASS_USER authenticatePassword only.
Real sudo from FIDO sessionsudo -k, then sudo -vFIDO behavior for the actual FIDO_USER session.
su, if configuredsu - FIDO_USER and su - BREAKGLASS_USERCorrect path per account. If su includes fido2-local-auth, su - FIDO_USER may succeed by FIDO instead of password.
Manual lockPress Super+L (or run dm-tool switch-to-greeter)Switches to the LightDM greeter. FIDO user authenticates through LightDM with PIN + touch; breakglass user remains available.
Idle-timeout lockWait for the configured idle timeout (posture chosen in section 16).Per your chosen idle posture: either no auto-lock (native idle disabled) or the native cinnamon-screensaver FIDO dialog. No flicker loop. Breakglass reachable via the greeter after a manual Super+L.
FIDO key removalRemove the FIDO token from an active graphical session.System switches to the LightDM greeter. User switching and breakglass login remain available.
Pre-classroom verification checklist (Cinnamon-specific, not yet validated on Mint). Before using this guide in class, confirm each of these on your actual Mint Cinnamon VM and record the observed behavior:
  • §12 greeter: Slick Greeter shows a usable FIDO PIN prompt (and the manual-username field, if enabled).
  • §16 manual lock: Super+L switches to the LightDM greeter; the built-in cinnamon-screensaver shortcut no longer fires.
  • §16 idle: your chosen idle posture behaves as expected (no auto-lock, or native locker with FIDO PAM).
  • §16 fallback PAM: pamtester cinnamon-screensaver FIDO_USER authenticate passes.
  • §17 removal: pulling the token switches to the greeter; check ID_VENDOR_ID/ID_MODEL_ID match your token and that ID_FIDO_TOKEN=1 is set on the remove event.

Reboot only after tests pass

Uses sudo
sudo reboot

19. Disable Unix password login for FIDO users

After the FIDO login path, LightDM greeter lock behavior, sudo behavior, breakglass account, and recovery path have been fully tested, the FIDO-enabled user can be made token-only by locking that user's Unix password. This prevents password-based authentication for that user while keeping the account itself valid for normal login, group membership, sudo policy, and PAM account/session checks.

Do not do this until the full test matrix passes. Keep a separate sudo-capable BREAKGLASS_USER with a known-working password. Do not lock the breakglass account's password.
Recovery model change: after passwd -l FIDO_USER, console TTY password recovery for that user is no longer available. Your password-based recovery path is BREAKGLASS_USER.

Lock the password, not the account. Use passwd -l for the FIDO user. Do not expire the account, disable the shell, delete the user, or remove normal group memberships.

Uses sudo
sudo passwd -l FIDO_USER

Verify the password state:

Uses sudo
sudo passwd -S FIDO_USER
sudo getent shadow FIDO_USER

The shadow password field should begin with !, indicating that password authentication is locked for that account. The account should still exist and should still be a member of fido-login.

Verify group membership:

Normal user shell
id FIDO_USER
getent group fido-login

Retest after locking the password

Run the core tests again before logging out or rebooting. Prefer operational tests from the actual FIDO_USER graphical session over synthetic-only tests.

From the actual FIDO_USER graphical session
sudo -k
sudo -v
# then press Super+L (or run: dm-tool switch-to-greeter)
Uses sudo
sudo pamtester lightdm FIDO_USER authenticate
sudo pamtester lightdm BREAKGLASS_USER authenticate
sudo pamtester cinnamon-screensaver FIDO_USER authenticate
TestExpected result
FIDO_USER through LightDMFIDO PIN + touch only.
FIDO_USER through real sudo -vFIDO PIN + touch only.
Manual lock (Super+L)Switches to the LightDM greeter, then FIDO PIN + touch through LightDM.
BREAKGLASS_USER through LightDMPassword only.

Confirm the Unix password itself is locked

If su has been modified to include fido2-local-auth, then su - FIDO_USER may still succeed through FIDO. That is expected. To prove that the Unix password itself is locked, test a password-only path such as an unmodified TTY login for FIDO_USER, or perform this check before enabling FIDO for su.

FIDO-protected PAM services should continue to work because fido2-local-auth exits successfully before falling through to common-auth.

Restore password login later, if needed

Uses sudo
sudo passwd -u FIDO_USER

Only unlock the password if you intentionally want password-based authentication restored for that account.

20. Optional: GNOME Keyring and Chrome/Chromium prompts

After converting a user to FIDO-only login, Chrome or Chromium may ask for the GNOME Keyring password when it tries to access stored browser secrets. This is expected.

GNOME Keyring is separate from FIDO/PAM login. GNOME Keyring normally unlocks the login keyring using the password entered during login. In the FIDO-only flow, the user authenticates with token PIN + touch, so there is no Unix password for pam_gnome_keyring.so to reuse.

This means FIDO2 can authenticate the desktop login, but it does not automatically decrypt an existing password-protected keyring. The keyring password remains separate.

20.1. Options

OptionBehaviorTradeoff
Keep the keyring passwordChrome/Chromium prompts for the keyring password when neededMost conservative; preserves separate protection for keyring secrets
Set the login keyring password blankChrome/Chromium stops prompting for the keyring passwordConvenient, but keyring secrets are no longer protected by a separate keyring password after session start
Restore password loginGNOME Keyring may auto-unlock from the login passwordUndermines the FIDO-only account goal
Security tradeoff: setting the keyring password blank is optional. It may be acceptable on a full-disk-encrypted laptop where the primary goal is removing reusable OS login passwords, but it reduces protection for secrets stored in the keyring during a logged-in session.

20.2. Install Seahorse

The graphical keyring editor may not already be installed. Install Seahorse:

Uses sudo
sudo apt install seahorse
Cinnamon note: Cinnamon is GTK/GNOME-derived, so the GNOME libraries Seahorse needs are usually already present and installation is typically clean — unlike the minimal XFCE case, where it can pull in a large dependency set. If apt nonetheless reports dependency errors, try the following:

sudo apt install --fix-broken
sudo apt update && sudo apt full-upgrade

If dependencies still cannot be resolved, an alternative is to manage the keyring password from the command line using secret-tool (from the libsecret-tools package) or by deleting and recreating the keyring file at ~/.local/share/keyrings/login.keyring. Note that deleting the keyring file will erase all stored keyring secrets.

Launch it:

Normal graphical session
seahorse

20.3. Set the login keyring password blank

  1. Open Passwords and Keys / Seahorse.
  2. Find the Login keyring.
  3. Right-click the Login keyring and choose Change Password.
  4. Enter the current keyring password.
  5. Leave the new password fields blank.
  6. Accept the warning about storing passwords unencrypted, if this matches your threat model.

After this, Chrome/Chromium should stop asking for the keyring password when launched inside the FIDO-only user session.

20.4. Do not automate this step

This walkthrough treats blanking the keyring password as an explicit user choice. Do not automate it in the PAM migration script, because it changes how local application secrets are protected.

21. Emergency rollback

If a PAM change breaks authentication and you still have a root-capable shell, remove the shared include references first:

Uses sudo
sudo sed -i '/fido2-local-auth/d' /etc/pam.d/lightdm /etc/pam.d/sudo /etc/pam.d/su /etc/pam.d/cinnamon-screensaver 2>/dev/null || true
sudo rm -f /etc/pam.d/fido2-local-auth
sudo rm -f /etc/lightdm/lightdm.conf.d/50-manual-login.conf
sudo rm -f /etc/udev/rules.d/85-fido-lock-on-remove.rules
sudo rm -f /etc/udev/rules.d/85-fido-lock-on-remove-test.rules
sudo rm -f /usr/local/sbin/fido-remove-switch-to-greeter
sudo rm -f /usr/local/sbin/lock-on-fido-remove
sudo udevadm control --reload-rules

If you need to restore backed-up PAM files:

Uses sudo
sudo test -e /etc/pam.d/lightdm.bak && sudo cp -a /etc/pam.d/lightdm.bak /etc/pam.d/lightdm || true
sudo test -e /etc/pam.d/sudo.bak && sudo cp -a /etc/pam.d/sudo.bak /etc/pam.d/sudo || true
sudo test -e /etc/pam.d/su.bak && sudo cp -a /etc/pam.d/su.bak /etc/pam.d/su || true
sudo test -e /etc/pam.d/cinnamon-screensaver.bak.before-fido2-local-auth && sudo cp -a /etc/pam.d/cinnamon-screensaver.bak.before-fido2-local-auth /etc/pam.d/cinnamon-screensaver || true
sudo test -e /etc/pam.d/cinnamon-screensaver.bak && sudo cp -a /etc/pam.d/cinnamon-screensaver.bak /etc/pam.d/cinnamon-screensaver || true
Reverting the Cinnamon lock keybinding: the Super+L greeter-switch keybinding from section 16 is per-user gsettings, not a root-owned file, so it is not touched by the rollback above. To restore Cinnamon's default lock shortcut, run as FIDO_USER: gsettings reset org.cinnamon.desktop.keybindings.media-keys screensaver and remove the custom0 entry from org.cinnamon.desktop.keybindings custom-list.

Restart display manager only when ready

Uses sudo
sudo systemctl restart lightdm

If you are locked out entirely, boot recovery or a live USB, mount the system, and remove the fido2-local-auth includes from the PAM files.

22. Option notes and policy choices

Common pam_u2f options used here

OptionMeaning
authfile=/etc/security/u2f_keysUse the central root-managed mapping file.
cue="..."Ask PAM/greeter to show a human cue. Graphical greeters may display it imperfectly.
pinverification=1Require the FIDO2 token PIN during authentication.
userverification=0Do not require a separate biometric or authenticator-level user-verification feature. The expected flow here is token PIN plus physical presence/touch.
PIN verification vs. user verification: In this walkthrough, pinverification=1 requires the token PIN. userverification=0 avoids requiring a separate biometric or authenticator-level UV feature. This is appropriate for KEY-ID FIDO+U2F style behavior where the desired flow is PIN + flashing-button touch.

pamu2fcfg options used here

OptionMeaning
-NEnroll a credential that requires PIN verification.
-u FIDO_USERCreate the mapping line for that user.
-nOutput only credential data so a backup token can be appended.

Why edit selected PAM services?

This guide edits LightDM, sudo, optional su, and the actual screen-locker PAM file. It does not edit common-auth globally, because a mistake there can break too many authentication paths at once.

Lock policy used here

This guide uses the LightDM greeter as the normal lock/unlock surface for FIDO users. The raw cinnamon-screensaver unlock dialog is kept PAM-valid as an idle-timeout fallback, but it is not the preferred primary unlock UI for FIDO-only use.

23. References and source notes

  • Packages (Debian/Ubuntu/Mint): libpam-u2f, pamu2fcfg, fido2-tools, and pamtester.
  • Cinnamon settings schemas: org.cinnamon.desktop.keybindings, org.cinnamon.desktop.keybindings.media-keys, org.cinnamon.desktop.screensaver, and org.cinnamon.desktop.session (via gsettings).
  • Yubico pam_u2f manual: documents authfile, cue, pinverification, userverification, nouserok, and passwordless examples.
  • Yubico pamu2fcfg manual: documents -N and -n.
  • libfido2 fido2-token and fido2-cred manuals: document listing tokens, setting/changing PINs, and make-credential tests with -t pin=true.
  • pam_succeed_if manual: documents group-based selection with user ingroup.
  • LightDM common configuration and sample config: document greeter-hide-users and greeter-show-manual-login.
  • loginctl manual: documents lock-sessions.
  • dm-tool manual: documents switch-to-greeter and the LightDM seat environment it requires.
  • udev documentation: covers matching USB device add/remove events with udev rules; systemd's fido_id builtin sets ID_FIDO_TOKEN.