Files
homelab-design/decisions/0030-mfa-yubikey-strategy.md
Billy D. 3580ee1223 docs: add ADRs 0029-0030 for Authentik registration and MFA
- 0029: User registration workflow with approval and group-based access
- 0030: MFA and Yubikey strategy for Authentik and Vaultwarden
2026-02-04 09:11:29 -05:00

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:

  1. Authentik - Central SSO for most applications
  2. 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

  1. WebAuthn/FIDO2 for both Authentik and Vaultwarden
  2. Yubikey OTP only
  3. 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

  1. User logs into Authentik
  2. Navigates to Settings → MFA Devices
  3. Clicks "Enroll WebAuthn Device"
  4. Inserts Yubikey and touches when prompted
  5. Names the device (e.g., "Yubikey 5 NFC - Primary")
  6. Optionally enrolls backup device or TOTP

Vaultwarden Configuration

Current State

Vaultwarden deployment has WebAuthn enabled by default, but admin panel configuration may be needed.

Required Configuration

1. Enable WebAuthn in Admin Panel

Access admin panel at https://vaultwarden.daviestechlabs.io/admin:

Settings → Advanced:
  Enable Web Vault: true (already set)
  
Two-Factor Authentication:
  Enable WebAuthn: true (verify this is set)

2. 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: 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

3. User Setup (WebAuthn - Already Available)

  1. Log into Vaultwarden web vault
  2. Go to Settings → Security → Two-step Login
  3. Click Manage next to "FIDO2 WebAuthn"
  4. Click "Register new key"
  5. Insert Yubikey and touch when prompted
  6. Name the key (e.g., "Yubikey 5 NFC")

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

  1. Admin accesses Authentik Admin → Directory → Users
  2. Find affected user
  3. Go to user's MFA Devices tab
  4. Delete lost device
  5. User can enroll new device on next login

Lost Yubikey - Vaultwarden

  1. User uses backup recovery code (generated at 2FA setup)
  2. Or admin accesses Vaultwarden admin panel
  3. Users → Find user → Disable 2FA
  4. 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

  1. Passkeys - Enable passwordless login with resident keys
  2. Conditional access - Require hardware key for sensitive operations only
  3. Device attestation - Verify Yubikey authenticity
  4. Session binding - Bind sessions to hardware key

References