Close

One touch, three paths: how immurok authenticates on macOS

A project log for immurok - a wireless fingerprint auth key

immurok is a small wireless fingerprint authentication device for Mac and Linux desktops

superdogsuperdog 07/08/2026 at 14:200 Comments

macOS has no single API you can plug a fingerprint into. immurok meets each authentication surface with the right mechanism — PAM, credential injection, or a GUI bridge — and keeps a hard security boundary around each. Here's the map, and an honest risk analysis.


There is no one place in macOS where you can say “a fingerprint touch counts as the password.” sudo goes through PAM. The App Store shows its own sheet. Screen unlock is a special world the system guards tightly. “Sign in with Apple” is rendered by a separate helper process. Each surface expects a different kind of proof.

So immurok doesn’t have one trick — it has three, and it picks the right one per surface. The unifying principle underneath is simple: the device only ever proves that a real, authenticated touch happened; the host decides what that touch is allowed to unlock. (How the device proves it — ECDH pairing, HMAC-signed events, biometrics that never leave the sensor — is the subject of the immurok security model. This post is about the host side.)

Path 1 — PAM + BLE: the device proves it

sudo, SSH key signing, and the system’s GUI authorization prompts all run a PAM stack. immurok ships a tiny module, pam_immurok.so, that sits at the front of the relevant /etc/pam.d services. When one of them authenticates, the module opens a Unix socket to the companion app, which asks your paired device for a challenge-response over BLE. Touch the sensor, the device returns a signed OK, PAM succeeds.

The important part: no password is involved anywhere. The credential is the cryptographically signed touch. There is nothing to store and nothing to type.

Path 2 — Credential injection: the host fills the field

The App Store, the Passwords app, and Safari’s “Sign in with Apple” sheet don’t go through PAM. They put a real secure text field on screen and wait for you to type. immurok watches the system’s focused accessibility element; when a whitelisted app focuses an AXSecureTextField, immurok writes the stored secret straight into it through the accessibility API and presses the sheet’s confirm button.

Two subtleties make this safe and possible:

Path 3 — The GUI bridge: host submits, PAM proves

Some GUI dialogs (the standalone SecurityAgent window) do run PAM, but only after a human clicks a button. immurok bridges the gap: on a touch it arms a short pre-authorization window scoped to the authorization service, then submits the field so the PAM chain runs and the pre-auth answers it. Screen unlock is the extreme case — PAM can’t dismiss a locked screen at all — so there the device simply types your password over its BLE HID keyboard.

Where the credential lives

The three paths differ most in one thing that matters for security: whether a real secret sits on your Mac at all.

The PAM path stores nothing — that’s its great property. The injection path buys convenience on surfaces PAM can’t reach, at the cost of keeping an actual password on the machine. immurok narrows that cost deliberately: secrets go in the Keychain, are captured only when you enable the feature, and are wiped the moment you turn it off.

Honest risk analysis

The takeaway is the same principle we started with, now with teeth: prove where macOS lets us, fill where it doesn’t, and never hand out authority without explicit, scoped, signed intent.

Discussions