~ writing/index.md

Passkeys for the homelab: Authelia + Windows Hello

The setup

My homelab SSO has run on Authelia for a while — password plus TOTP, behind Caddy, reached through a Cloudflare Tunnel. It works, but TOTP is still a shared-secret dance and phishing-adjacent attacks keep making it look worse. I wanted to see if passkeys were practical for a self-hoster today, with Authelia acting as the identity provider and Windows Hello as the authenticator.

I did not need to upgrade Authelia to make this work. The installed .deb was already on a 4.39.x release with WebAuthn support. In my setup Authelia runs as a package inside an LXC, not a container, so "upgrade" would mean apt, not a Docker pull. I skipped the version bump and changed config instead.

The config

The change was small:

webauthn:
  display_name: 'gregsplace.cc'
  enable_passkey_login: true
  experimental_enable_passkey_uv_two_factors: true
  selection_criteria:
    attachment: 'platform'

enable_passkey_login adds passkeys as a login option, but by default it counts as single-factor. My access control policy requires two-factor for *.gregsplace.cc, so a plain passkey login would still prompt for TOTP and defeat the point. The experimental flag treats user-verified passkeys as satisfying the two-factor requirement. Windows Hello always does user verification, so it qualifies. I accepted the experimental flag because password-plus-TOTP stays available as fallback — there is no lockout risk.

selection_criteria.attachment: 'platform' steers the browser toward a platform authenticator like Windows Hello during registration. Without it, the browser offers the roaming "touch your security key" flow, which is not what I wanted on the laptop.

The enrollment dance

Registration is where the WebAuthn ceremony lives. The browser and Authelia exchange a challenge, the authenticator signs it, and Authelia stores the public key. In theory it is three clicks. In practice the browser caches the old challenge options across restarts, and if you restart Authelia after a config change, the page in Chrome still offers the previous ceremony until you hard-reload with Ctrl+Shift+R. That cost me ten minutes of staring at a modal that should not have existed. The fix was a browser refresh, not a config change.

Only Chrome-plus-Windows-Hello drove the platform authenticator reliably on this machine. Firefox on Windows could not initiate Hello here, so I standardized on Chrome for enrollment. I registered two credentials: windows-laptop for the PC's Hello sensor, and macbook-fingerprint for the MacBook. Because Apple syncs passkeys through iCloud, the MacBook credential also covers the iPhone — iOS reported it as already registered when I tried to add the phone separately. That is the difference between a synced passkey and a device-bound credential.

The edit pattern

For a live SSO service, I do not edit config in place and hope. The pattern is: back up the current file, append the new config, validate with authelia config validate, restart the service, hit /api/health for a 200, and auto-rollback to the backup if anything fails. I listed existing credentials with authelia storage user webauthn list greg afterward to confirm both registered cleanly.

What works now

I can log into the homelab with Windows Hello. No password, no six-digit code, no unlocking a phone. The credential never leaves the device, it is resistant to phishing by construction, and the fallback path is still there if the experimental flag ever misbehaves. The iCloud-synced credential means the MacBook and iPhone share the same trust anchor, so I did not have to enroll every device individually.

Takeaways

  • You probably do not need a new Authelia version for passkeys. Check your current version first; WebAuthn support is already in recent 4.39.x builds.
  • Treat user-verified platform authenticators as two-factor only if your policy needs it, and only with a fallback method enabled. Experimental flags are fine when the escape hatch is real.
  • Hard-reload the browser after restarting the IdP during enrollment. The ceremony is stateful, and stale options are the most likely reason registration looks broken.
  • Use Chrome for Windows Hello enrollment; Firefox on Windows did not drive the platform authenticator in my case.
  • Prefer the live-edit pattern for anything that answers the front door: backup, validate, restart, health-check, rollback. SSO is not a place to wing it.

Passkeys are not theoretical anymore for self-hosters. With Authelia as the IdP, a standard WebAuthn config block, and the platform authenticator already built into the laptop, the gap between enterprise SSO and a one-person homelab got a lot smaller.

← back to writing