| Placeholder | Meaning |
|---|---|
FIDO_USER | Lab account that will use the FIDO token |
BREAKGLASS_USER | Separate sudo-capable, password-only account — never add to fido-login |
/dev/hidraw1 | Token device path from 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. |
096e / 0858 | Token vendor/model IDs from udevadm monitor — check per token |
Do not reorder. Do not skip §11 test service or §14 Core Checkpoint.
fido2-token -L returns nothing"fido2-token -L.fido-login group → id FIDO_USERsudo ls -l /etc/security/u2f_keys # expect: -rw-r----- root fido-login
sudo grep "^FIDO_USER:" /etc/security/u2f_keys
id FIDO_USER — does fido-login appear?usermod?@include fido2-local-auth in the right PAM file?
sudo grep fido2-local-auth /etc/pam.d/lightdm
sudo cat /etc/pam.d/fido2-local-auth
xflock4 does nothing / fails from terminal"xflock4 needs graphical session env vars. Only works from the original XFCE terminal session — not from a su - shell or SSH.
echo "$DISPLAY"
echo "$XDG_RUNTIME_DIR"
echo "$DBUS_SESSION_BUS_ADDRESS"
sudo package overwrote /etc/pam.d/sudo, removing the FIDO include.BREAKGLASS_USER first, then:
sudo /usr/local/sbin/fido2-sudo-pam-guard
sudo grep fido2-local-auth /etc/pam.d/sudo
sudo -k && sudo -v
sudo journalctl -b --since "3 minutes ago" | grep -i fido-udevudevadm monitor againls -l /usr/local/sbin/fido-remove-switch-to-greetersudo /usr/local/sbin/fido-remove-switch-to-greetersudo journalctl -b --since "5 minutes ago" | \
grep -Ei 'fido-switch-greeter|dm-tool|udev'
FIDO_ERR_PIN_INVALID = wrong PIN.FIDO_ERR_PIN_REQUIRED = missing -t pin=true flag — rerun with it.fido2-token -I /dev/hidraw1 (look for PIN management = true).
BREAKGLASS_USER — this is what it's for.fido2-local-auth includes from PAM files. See Emergency Rollback.
sudo grep "^FIDO_USER:" /etc/security/u2f_keys
sudo cat /etc/security/u2f_keys # check whole file
id FIDO_USER # verify exact username
lsusb
fido2-token -L # expect: /dev/hidraw1: VENDOR MODEL FIDO+U2F
fido2-token -L # list tokens; note /dev/hidraw1
fido2-token -I /dev/hidraw1 # inspect: firmware, PIN state, retries
fido2-token -S /dev/hidraw1 # set a new PIN
fido2-token -C /dev/hidraw1 # change existing PIN
fido-token-test.sh[7]) so the tool can never wipe it.Save it, then on the lab box: chmod +x fido-token-test.sh && ./fido-token-test.sh. Non-interactive sweep: ./fido-token-test.sh --batch --report. Full option list: ./fido-token-test.sh --help. Requires fido2-tools (optionally ykman, udevadm).
sudo apt update
sudo apt install libpam-u2f pamu2fcfg fido2-tools pamtester
rm -rf /tmp/fido2-login-test && mkdir -p /tmp/fido2-login-test && cd /tmp/fido2-login-test
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
fido2-cred -M -t pin=true -i cred_param /dev/hidraw1 | fido2-cred -V -o cred
ls -l cred
cd && rm -rf /tmp/fido2-login-test
Expected: PIN prompt → LED flash → touch → cred file created. FIDO_ERR_PIN_INVALID = wrong PIN. FIDO_ERR_PIN_REQUIRED = missing -t pin=true.
usermod will get a password prompt in pamtester and assume PAM is broken. Check group membership with id FIDO_USER first.sudo groupadd --force fido-login
sudo usermod -aG fido-login FIDO_USER
id FIDO_USER # fido-login must appear
getent group fido-login # FIDO_USER must be listed
# Enroll primary token
pamu2fcfg -N -u FIDO_USER > /tmp/u2f_keys-FIDO_USER
cat /tmp/u2f_keys-FIDO_USER # line must start with FIDO_USER:
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 # expect: -rw-r----- root fido-login
sudo grep "^FIDO_USER:" /etc/security/u2f_keys
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 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
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
sudo pamtester fido2-test FIDO_USER authenticate # FIDO PIN + touch
sudo pamtester fido2-test BREAKGLASS_USER authenticate # password only
If pamtester fails → see Triage: "cannot retrieve authentication info".
sudo cp -a /etc/pam.d/lightdm /etc/pam.d/lightdm.bak
sudo editor /etc/pam.d/lightdm
# Insert @include fido2-local-auth immediately above @include common-auth
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
sudo pamtester lightdm FIDO_USER authenticate # FIDO PIN + touch
sudo pamtester lightdm BREAKGLASS_USER authenticate # password
sudo cp -a /etc/pam.d/sudo /etc/pam.d/sudo.bak
sudo editor /etc/pam.d/sudo
# Insert @include fido2-local-auth immediately above @include common-auth
sudo -k && sudo -v # test from FIDO_USER session
passwd -l) is done and apt later overwrites /etc/pam.d/sudo, FIDO_USER loses all sudo access. BREAKGLASS_USER becomes the only recovery path. Install and verify the guard before §19.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
sudo tee /etc/apt/apt.conf.d/99-fido2-sudo-pam-guard >/dev/null <<'EOF'
{{EMBED:config/99-fido2-sudo-pam-guard}}
EOF
# Verify the guard works:
sudo grep fido2-local-auth /etc/pam.d/sudo
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
sudo -k && sudo -v
passwd -l until all five pass. Keep a root-capable shell open.sudo pamtester fido2-test FIDO_USER authenticate # FIDO PIN + touch
sudo pamtester fido2-test BREAKGLASS_USER authenticate # password
sudo pamtester lightdm FIDO_USER authenticate # FIDO PIN + touch
sudo pamtester lightdm BREAKGLASS_USER authenticate # password
sudo -k && sudo -v # FIDO PIN + touch (as FIDO_USER)
| Test | Expected |
|---|---|
| Test service — FIDO user | FIDO PIN + touch |
| Test service — breakglass | Password only |
| LightDM — FIDO user | FIDO PIN + touch |
| LightDM — breakglass | Password only |
| Real sudo (as FIDO_USER) | FIDO PIN + touch |
sudo cp -a /etc/pam.d/su /etc/pam.d/su.bak
sudo editor /etc/pam.d/su
# Keep pam_rootok.so FIRST, then @include fido2-local-auth above @include common-auth
su - FIDO_USER # FIDO if token present
su - BREAKGLASS_USER # password
xfce4-screensaver unlock dialog is not the primary FIDO unlock surface. The LightDM greeter is. Keep screensaver PAM valid as a fallback only.sudo cp -a /etc/pam.d/xfce4-screensaver \
/etc/pam.d/xfce4-screensaver.bak.before-fido2-local-auth
sudo editor /etc/pam.d/xfce4-screensaver
# Content:
# auth include fido2-local-auth
# auth include common-auth
# auth optional pam_gnome_keyring.so
# account required pam_permit.so
sudo pamtester xfce4-screensaver FIDO_USER authenticate
sudo pamtester xfce4-screensaver FIDO_USER acct_mgmt
sudo pamtester xfce4-screensaver BREAKGLASS_USER authenticate
sudo pamtester xfce4-screensaver BREAKGLASS_USER acct_mgmt
xfconf-query -c xfce4-session -p /general/LockCommand \
--create -t string -s "dm-tool switch-to-greeter"
xfconf-query -c xfce4-session -p /general/LockCommand # verify output
xflock4 # test manual lock
pgrep -a 'xfce4-screensaver|light-locker|xscreensaver|xsecurelock' # active lockers?
sudo udevadm monitor --udev --environment
# Remove token → look for hidraw remove event with ID_FIDO_TOKEN=1
# Record ID_VENDOR_ID and ID_MODEL_ID
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 token, then:
sudo journalctl -b --since "2 minutes ago" | grep -i fido-udev-test
# If confirmed, remove test rule:
sudo rm -f /etc/udev/rules.d/85-fido-lock-on-remove-test.rules
sudo udevadm control --reload-rules
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
# Test helper manually:
sudo /usr/local/sbin/fido-remove-switch-to-greeter
# Post-removal log:
sudo journalctl -b --since "3 minutes ago" | \
grep -Ei 'fido-switch-greeter|fido-udev|dm-tool|lightdm|greeter'
sudo pamtester fido2-test FIDO_USER authenticate
sudo pamtester fido2-test BREAKGLASS_USER authenticate
sudo pamtester lightdm FIDO_USER authenticate
sudo pamtester lightdm BREAKGLASS_USER authenticate
sudo -k && sudo -v
| Test | Command / Action | Expected |
|---|---|---|
| Test service — FIDO | sudo pamtester fido2-test FIDO_USER authenticate | FIDO PIN + touch |
| Test service — breakglass | sudo pamtester fido2-test BREAKGLASS_USER authenticate | Password |
| LightDM — FIDO | sudo pamtester lightdm FIDO_USER authenticate | FIDO PIN + touch |
| LightDM — breakglass | sudo pamtester lightdm BREAKGLASS_USER authenticate | Password |
| Real sudo | sudo -k then sudo -v | FIDO PIN + touch |
| su (if configured) | su - FIDO_USER / su - BREAKGLASS_USER | FIDO / password |
| Manual lock | xflock4 from XFCE session | Switches to LightDM greeter |
| Idle timeout | Wait for configured timeout | Greeter switch; no flicker loop |
| Token removal | Remove token from active session | Switches to LightDM greeter |
sudo reboot # only after all tests pass
sudo passwd -l FIDO_USER # lock password
sudo passwd -S FIDO_USER # verify: field begins with !
sudo getent shadow FIDO_USER
id FIDO_USER # still in fido-login?
# Re-test after locking:
sudo -k && sudo -v
xflock4
sudo pamtester lightdm FIDO_USER authenticate
sudo pamtester lightdm BREAKGLASS_USER authenticate
sudo pamtester xfce4-screensaver FIDO_USER authenticate
# Restore if needed:
sudo passwd -u FIDO_USER
Chrome/Chromium prompting for keyring password after FIDO-only login is expected behavior — FIDO login doesn't unlock the keyring automatically.
sudo apt install seahorse
seahorse # Passwords and Keys → Login → Change Password → leave new password blank
# Token
fido2-token -L
lsusb
# Group / mapping
id FIDO_USER
getent group fido-login
sudo ls -l /etc/security/u2f_keys
sudo grep "^FIDO_USER:" /etc/security/u2f_keys
# PAM state
sudo cat /etc/pam.d/fido2-local-auth
sudo grep fido2-local-auth /etc/pam.d/lightdm
sudo grep fido2-local-auth /etc/pam.d/sudo
# Graphical session env — run from FIDO_USER XFCE terminal
echo "$DISPLAY" && echo "$XDG_RUNTIME_DIR" && echo "$DBUS_SESSION_BUS_ADDRESS"
# Active screen lockers
pgrep -a 'xfce4-screensaver|light-locker|xscreensaver|xsecurelock'
# dm-tool present?
command -v dm-tool
# Log tail — token removal / greeter / PAM events
sudo journalctl -b --since "5 minutes ago" | \
grep -Ei 'fido-switch-greeter|fido-udev|dm-tool|lightdm|pam_u2f|greeter'
# sudo guard log
sudo journalctl -b | grep fido2-sudo-pam-guard
Wipes all credentials and removes the PIN, returning the FIDO2 application to factory state for the next student. Uses the CTAP2 authenticatorReset command.
| What gets reset | What does NOT get reset |
|---|---|
| All FIDO2/U2F credentials (resident + non-resident) | YubiKey OTP slots, PIV certificates, OATH credentials — separate applications, unaffected |
| FIDO2 PIN | |
| Credential counter |
fido2-token -R (any FIDO2 token)FIDO_ERR_NOT_ALLOWED. Fix: unplug first, run the command, then replug and press promptly.# Step 1: unplug the token
# Step 2: run the command — it blocks waiting for the device to appear
fido2-token -R /dev/hidraw1
# Step 3: plug the token back in — do this and the next step within 10 seconds
# Step 4: press the button when the LED flashes (same 10-second window from power-up)
fido2-token -L # confirm device path
fido2-token -I /dev/hidraw1 # PIN management should show no PIN set
ykman fido resetykman handles the power-up timing requirement and prompts for physical confirmation. Easier to use than fido2-token -R when available.
ykman fido reset # interactive: prompts to unplug/replug, then touch
ykman fido reset --force # skip confirmation prompt (still requires physical touch)
| Method | Steps |
|---|---|
| Snapshot restore (preferred) | Restore VM to pre-lab snapshot — resets everything cleanly |
| Manual rollback | Run Emergency Rollback section, then the commands below |
sudo rm -f /etc/security/u2f_keys
sudo gpasswd -d FIDO_USER fido-login # remove user from group
sudo passwd -u FIDO_USER # unlock password if locked in §19
fido2-local-auth includes.sudo sed -i '/fido2-local-auth/d' \
/etc/pam.d/lightdm \
/etc/pam.d/sudo \
/etc/pam.d/su \
/etc/pam.d/xfce4-screensaver 2>/dev/null || true
sudo rm -f /etc/pam.d/fido2-local-auth
sudo rm -f /etc/pam.d/fido2-test
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 rm -f /etc/apt/apt.conf.d/99-fido2-sudo-pam-guard
sudo rm -f /usr/local/sbin/fido2-sudo-pam-guard
sudo udevadm control --reload-rules
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/xfce4-screensaver.bak.before-fido2-local-auth && \
sudo cp -a /etc/pam.d/xfce4-screensaver.bak.before-fido2-local-auth \
/etc/pam.d/xfce4-screensaver || true
sudo systemctl restart lightdm