PAM integration

deploy.sh adds auth sufficient pam_exec.so quiet stdout /usr/local/bin/vinoauthface-auth to:

Service File Covers
sudo /etc/pam.d/sudo sudo
gdm-password /etc/pam.d/gdm-password GNOME lock screen
swaylock /etc/pam.d/swaylock swaylock
polkit-1 /etc/pam.d/polkit-1 polkit prompts
kde-fingerprint or kde-smartcard /etc/pam.d/kde-fingerprint or kde-smartcard KDE lock screen (one of the two, see KDE)
cosmic-greeter /etc/pam.d/cosmic-greeter COSMIC lock screen and greeter

The Plasma login screen is opt-in and set separately: see Login screen.

The line goes just above the first auth line that actually authenticates: pam_unix, pam_sss, pam_fprintd, pam_u2f, or an include/substack/@include of another stack. Gates above that point, like pam_nologin, pam_faillock preauth and Fedora’s pam_selinux_permit, still run before a face match can end the stack. Gates inside an included stack (Fedora’s system-auth, say) don’t.

If a stack the service includes already runs vinoAuthFace (added by hand, an authselect profile, an older install), deploy.sh skips the service rather than scan the camera twice per attempt.

sufficient means a face match (exit 0) authenticates immediately. Anything else (no match, no camera, timeout, lockout) falls through to the password prompt. quiet keeps pam_exec chatter out of the unlock UI.

While scanning, vinoauthface-auth shows Looking for your face...:

  • With a terminal (sudo in a terminal or on a VT), it’s written to the controlling terminal and erased when the scan ends.
  • Without one (lock screens, login screens, polkit agents), it’s written once to stdout, which stdout has pam_exec relay to the application as a PAM info message, as it arrives. The application decides how to show it and replaces it with its own prompt if the scan falls through. pam_exec relays stderr the same way, so in this mode vinoauthface-auth sends its stderr to /dev/null: errors are in journalctl -t vinoauthface-auth either way.

Only sudo (and sudo -i, sudo su -, which authenticate through it) is covered on a text console. su isn’t: it authenticates the target account, so a face can only ever match the caller’s own account. Console login isn’t wired up either.

Installs from before this change have the line without stdout and stay silent on lock screens until deploy.sh is re-run (update.sh doesn’t touch PAM).

KDE

KScreenLocker runs two background PAM services next to the password field, kde-fingerprint and kde-smartcard. deploy.sh puts face in one of them, so the KDE lock screen unlocks hands-free: look at the camera and it opens, or type your password as usual.

kde-fingerprint kde-smartcard Face goes in Line
No pam_fprintd any kde-fingerprint [success=done new_authtok_reqd=done default=die]
Runs pam_fprintd No smartcard module kde-smartcard [success=done new_authtok_reqd=done default=die]
Runs pam_fprintd Runs pam_pkcs11, pam_p11 or pam_sss, or is missing kde-fingerprint sufficient

pam_fprintd and the smartcard modules count in the service’s own file or in a stack it includes (Fedora’s fingerprint-auth and smartcard-auth). In the smartcard slot, face and finger run at the same time and Plasma’s hint reads “(or scan your smartcard)”. Sharing the fingerprint slot with fprintd, face runs first and the reader waits until the scan ends. Re-running deploy.sh after enabling or disabling fingerprint login moves face to match.

In a slot of its own, a miss ends the stack with an error instead of falling through. On Fedora the rest of the stack is a stub that answers “unavailable”, and KScreenLocker stops using a service that answers that until the next lock.

KScreenLocker starts these services when the lock screen wakes (a key or mouse move), not when it locks, so walking up to a locked laptop and moving the mouse starts a scan. It doesn’t retry one that missed: moving the mouse again does nothing. To scan again, press Enter on an empty password field (or type a wrong one). The failed password restarts every service 3 seconds later.

Login screen

Face unlock at the Plasma login screen has three modes, off by default:

Mode PAM At the login screen
off Nothing Password only
both required line below plasmalogin’s password stack Type your password, then look at the camera. Both must pass. The password still unlocks KWallet
face sufficient line above the password, in plasmalogin-fingerprint if the system has it, plasmalogin if not A match logs you in; anything else falls back to the password. KWallet stays locked (see Keyrings)

Set it with sudo ./deploy.sh --login=off|both|face (or FACE_AUTH_LOGIN), the tray’s “Login screen” submenu, or sudo /usr/local/share/face-auth/login-mode.sh off|both|face directly. login-mode.sh status prints the current one. A deploy or upgrade without --login keeps whatever is set.

plasmalogin-fingerprint runs hands-free beside the password field. Fedora 45 ships only plasmalogin, so there face needs you to select your account and press Enter with the password field empty. Only one of the two is ever wired, or the greeter would scan twice.

In both, the camera is a hard requirement. A covered camera, a closed lid, an active face lockout or a broken NPU driver means no graphical login until it’s fixed; log in on a text console (Ctrl+Alt+F3) and run sudo /usr/local/share/face-auth/login-mode.sh off. A wrong password still starts a scan, since PAM runs the rest of the stack either way; the login fails regardless.

GDM and COSMIC aren’t covered: gdm-password and cosmic-greeter also run their lock screens, where they keep the face-or-password line.

The greeter runs face-auth in SELinux’s xdm_t, which needs deploy.sh’s policy (see install.md). Sealed templates (seal_embeddings = true) are unsealed there by vinoauthface-unseal in its own domain, so the greeter never gets the TPM or systemd’s host key. An install without the helper (a release from before it) can’t unseal at the greeter: face falls back to the password, and login-mode.sh refuses both, which nobody could get past. Re-run deploy.sh to fix that.

Plasma before 6.7 has a bug where a biometric unlock counts against pam_faillock (kscreenlocker 29d01bf7), so repeated face unlocks can lock the password out until it expires. Update Plasma or drop pam_faillock from the stack if you hit it.

COSMIC

cosmic-greeter is one service for both the lock screen and the greeter. It shows a single PAM message at a time, so the password field is hidden while vinoAuthFace scans, and there is no text to say so. At login it runs as the greeter user rather than the person unlocking.

Vendor-only services

On image-based distros these services often exist only as a vendor default in /usr/lib/pam.d. deploy.sh copies that file to /etc/pam.d first to have something to patch (as it does for polkit-1), and uninstall.sh deletes the copy rather than “restoring” a file that never existed.

polkit

polkit-1 covers every polkit auth_self prompt: pkexec, package-manager GUIs, settings changes, and apps like Bitwarden that ask polkit to re-authenticate you. Most distros ship only the vendor default in /usr/lib/pam.d/polkit-1, so deploy.sh copies it to /etc/pam.d/polkit-1 first to have something to patch. uninstall.sh deletes that copy rather than “restoring” a file that never existed.

vinoAuthFace only authenticates the account running the prompt. When an admin authenticates on behalf of another logged-in user, it falls through to the password.

Bitwarden biometric unlock

If a Bitwarden desktop client is installed (native, Flatpak or Snap), deploy.sh also installs Bitwarden’s polkit action (/usr/share/polkit-1/actions/com.bitwarden.Bitwarden.policy). Flatpak and Snap builds are sandboxed and can’t write it themselves. The content is transcribed from Bitwarden’s own source (os-biometrics-linux.service.ts in bitwarden/clients), not downloaded. Then enable Settings → Unlock with system authentication in Bitwarden.

Keyrings

A face match means PAM never sees a password. Any module that unlocks a secret store from the login password has nothing to unlock it with, so after a face login:

Store Module After face login
KWallet pam_kwallet5 Locked
oo7 (Fedora 45’s default Secret Service) pam_oo7 Locked
GNOME Keyring pam_gnome_keyring Locked

The first app that needs a secret asks for the password once, then the store stays open for the session.

  • Lock screen unlock is fine. The store was opened at login and stays open across screen locks, so there’s nothing for vinoAuthFace to gate there.
  • Plasma Login Manager quirk. If you typed a password and your face matched first, PLM still hands the typed text to pam_kwallet5, so the wallet unlocks. A mistyped password gives a face login with a locked wallet.
  • No TPM-sealed password. Some projects seal a copy of the login password to the TPM and feed it back as PAM_AUTHTOK after a face match. pam_exec can’t set PAM_AUTHTOK, so that needs a real PAM .so module, which this project doesn’t ship. Not planned.