13 KiB
MFA and Yubikey Strategy
- Status: proposed
- Date: 2026-02-04
- Deciders: Billy
- Technical Story: Enable hardware security key (Yubikey) authentication across homelab applications
Context and Problem Statement
Password-only authentication is vulnerable to phishing and credential theft. Hardware security keys (Yubikeys) provide phishing-resistant authentication through WebAuthn/FIDO2. The homelab uses multiple authentication points:
- Authentik - Central SSO for most applications
- Vaultwarden - Password manager (independent auth)
How do we enable Yubikey support across these authentication points while maintaining usability?
Decision Drivers
- Phishing-resistant authentication for sensitive applications
- Flexibility - support both hardware keys and TOTP
- User experience - single Yubikey works everywhere
- Fallback options - don't lock users out if key is lost
- Future-proof - support passkeys and newer standards
Considered Options
- WebAuthn/FIDO2 for both Authentik and Vaultwarden
- Yubikey OTP only
- TOTP only (no hardware key support)
Decision Outcome
Chosen option: Option 1 - WebAuthn/FIDO2 for both Authentik and Vaultwarden
WebAuthn provides the best security (phishing-resistant) and user experience (touch to authenticate). Both Authentik and Vaultwarden support WebAuthn natively.
Positive Consequences
- Phishing-resistant authentication
- Single Yubikey works for all applications
- No external dependencies (unlike Yubikey OTP)
- Supports passkeys for future passwordless auth
- Hardware-bound credentials can't be copied
Negative Consequences
- Requires modern browser with WebAuthn support
- Users must have physical access to key
- Key loss requires recovery process
Implementation Status
| Application | WebAuthn Support | Current Status | Action Required |
|---|---|---|---|
| Authentik | ✅ Native | ✅ Working | Configure enforcement policies |
| Vaultwarden | ✅ Native | ⚠️ Partial | Enable in admin settings |
Authentik Configuration
Current State
Authentik has WebAuthn support built-in. Users can already enroll devices via:
- Settings → MFA Devices → Enroll WebAuthn Device
Required Configuration
1. Create WebAuthn Authenticator Stage
In Admin → Flows & Stages → Stages:
Stage: authenticator-webauthn-setup
Type: Authenticator WebAuthn Setup Stage
Name: authenticator-webauthn-setup
User verification: preferred
Resident key requirement: preferred
Authenticator attachment: cross-platform
Stage: authenticator-webauthn-validation
Type: Authenticator Validation Stage
Name: authenticator-webauthn-validation
Device classes: WebAuthn, TOTP (allow both)
Not configured action: skip
2. Bind to Authentication Flow
Edit the default authentication flow to include MFA:
Flow: default-authentication-flow
Stages (in order):
1. identification (username/email)
2. password
3. authenticator-webauthn-validation ← Add this
4. user-login
3. Create MFA Enforcement Policies
Policy: enforce-mfa-admins
# Expression Policy
# Requires WebAuthn for admins
if ak_is_group_member(request.user, name="homelab-admins"):
from authentik.stages.authenticator_webauthn.models import WebAuthnDevice
if not WebAuthnDevice.objects.filter(user=request.user).exists():
ak_message("Administrators must enroll a hardware security key (Yubikey)")
return False
return True
Policy: enforce-mfa-users
# Expression Policy
# Requires any MFA for users
if ak_is_group_member(request.user, name="homelab-users"):
from authentik.stages.authenticator_totp.models import TOTPDevice
from authentik.stages.authenticator_webauthn.models import WebAuthnDevice
has_totp = TOTPDevice.objects.filter(user=request.user, confirmed=True).exists()
has_webauthn = WebAuthnDevice.objects.filter(user=request.user).exists()
if not (has_totp or has_webauthn):
ak_message("Please enroll an MFA device (authenticator app or security key)")
return False
return True
4. User Enrollment Flow
- User logs into Authentik
- Navigates to Settings → MFA Devices
- Clicks "Enroll WebAuthn Device"
- Inserts Yubikey and touches when prompted
- Names the device (e.g., "Yubikey 5 NFC - Primary")
- Optionally enrolls backup device or TOTP
Vaultwarden Configuration
Current State
Vaultwarden deployment has WebAuthn support built-in. Configuration is done via the admin panel.
Required Configuration
1. Enable WebAuthn in Admin Panel
Access admin panel at https://vaultwarden.daviestechlabs.io/admin:
- Navigate to Settings section
- Find Yubikey settings:
- For WebAuthn/FIDO2: No additional configuration needed (enabled by default)
- For Yubikey OTP: Requires Client ID and Secret Key from Yubico
- Find Two-Factor Authentication or General settings:
- Verify WebAuthn is not disabled
- Click Save if any changes made
2. User Setup (WebAuthn)
- Log into Vaultwarden web vault
- Go to Settings → Security → Two-step Login
- Click Manage next to "FIDO2 WebAuthn"
- Click "Register new key"
- Insert Yubikey and touch when prompted
- Name the key (e.g., "Yubikey 5 NFC")
3. Optional: Enable Yubikey OTP
If users want Yubikey OTP as an additional option (the 44-character string feature):
Step 1: Get Yubico API Credentials
Visit: https://upgrade.yubico.com/getapikey/
Step 2: Enter credentials in Admin Panel
In the Vaultwarden admin panel → Yubikey section:
- Enter Client ID
- Enter Secret Key
- Click Save
Alternatively, for GitOps management:
Step 2b: Store credentials in Vault
vault kv put kv/vaultwarden-yubico \
client_id="YOUR_CLIENT_ID" \
secret_key="YOUR_SECRET_KEY"
Step 3: Create ExternalSecret
Add to /home/billy/homelab-k8s2/kubernetes/apps/security/vaultwarden/app/externalsecret.yaml:
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: vaultwarden-yubico
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: vault
target:
name: vaultwarden-yubico
creationPolicy: Owner
data:
- secretKey: YUBICO_CLIENT_ID
remoteRef:
key: kv/data/vaultwarden-yubico
property: client_id
- secretKey: YUBICO_SECRET_KEY
remoteRef:
key: kv/data/vaultwarden-yubico
property: secret_key
Step 4: Update Deployment
Add to /home/billy/homelab-k8s2/kubernetes/apps/security/vaultwarden/app/deployment.yaml:
envFrom:
- secretRef:
name: vaultwarden-db-credentials
- secretRef:
name: vaultwarden-yubico # Add this
Status: ⏳ NOT IMPLEMENTED - Requires Yubico API credentials
MFA Requirements by User Group
| Group | MFA Requirement | Allowed Methods |
|---|---|---|
| homelab-admins | Required | WebAuthn only |
| homelab-users | Required | WebAuthn or TOTP |
| homelab-guests | Optional | WebAuthn or TOTP |
| pending-approval | Not required | N/A |
Recovery Procedures
Lost Yubikey - Authentik
- Admin accesses Authentik Admin → Directory → Users
- Find affected user
- Go to user's MFA Devices tab
- Delete lost device
- User can enroll new device on next login
Lost Yubikey - Vaultwarden
- User uses backup recovery code (generated at 2FA setup)
- Or admin accesses Vaultwarden admin panel
- Users → Find user → Disable 2FA
- User can re-enable with new device
Best Practice: Backup Keys
Recommend users enroll:
- Primary Yubikey (carried daily)
- Backup Yubikey (stored securely at home)
- TOTP as fallback (if allowed by policy)
Supported Yubikey Models
| Model | WebAuthn | NFC | USB-C | Recommended For |
|---|---|---|---|---|
| Yubikey 5 NFC | ✅ | ✅ | ❌ | Mobile + Desktop (USB-A) |
| Yubikey 5C NFC | ✅ | ✅ | ✅ | Modern laptops |
| Yubikey 5 Nano | ✅ | ❌ | ❌ | Always-in desktop |
| Security Key NFC | ✅ | ✅ | ❌ | Budget option |
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ User Login │
└──────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Authentik SSO │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Password │───▶│ WebAuthn │───▶│ Session │ │
│ │ Stage │ │ Validation │ │ Created │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ │ Yubikey │ │
│ │ Touch │ │
│ └─────────────┘ │
└──────────────────────────────┬──────────────────────────────────┘
│ SSO (no MFA needed again)
┌────────────────────┼────────────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Affine │ │ Nextcloud│ │ Immich │
└──────────┘ └──────────┘ └──────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Vaultwarden (Separate) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Master │───▶│ WebAuthn │───▶│ Vault │ │
│ │ Password │ │ (2FA) │ │ Unlocked │ │
│ └─────────────┘ └──────┬──────┘ └─────────────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ │ Yubikey │ │
│ │ Touch │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Testing Checklist
Authentik WebAuthn
- Enroll Yubikey as admin user
- Verify login requires Yubikey touch
- Test SSO to Affine with Yubikey
- Test recovery with backup device
- Verify non-admin can use TOTP instead
Vaultwarden WebAuthn
- Enable WebAuthn in admin panel
- Enroll Yubikey for test user
- Verify vault unlock requires Yubikey
- Test with browser extension
- Test recovery code flow
Future Enhancements
- Passkeys - Enable passwordless login with resident keys
- Conditional access - Require hardware key for sensitive operations only
- Device attestation - Verify Yubikey authenticity
- Session binding - Bind sessions to hardware key