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
This commit is contained in:
340
decisions/0029-authentik-user-registration-workflow.md
Normal file
340
decisions/0029-authentik-user-registration-workflow.md
Normal file
@@ -0,0 +1,340 @@
|
||||
# Authentik User Registration and Approval Workflow
|
||||
|
||||
* Status: accepted
|
||||
* Date: 2026-02-04
|
||||
* Deciders: Billy
|
||||
* Technical Story: Control access to homelab applications through vetted user registration
|
||||
|
||||
## Context and Problem Statement
|
||||
|
||||
The homelab hosts applications that should only be accessible to trusted users (family, close friends). While Authentik provides SSO, we need a controlled registration process where:
|
||||
1. Users can self-register
|
||||
2. An admin reviews and approves registrations
|
||||
3. Approved users get access only to specific applications based on their role
|
||||
|
||||
How do we implement a user registration workflow with approval and conditional application access?
|
||||
|
||||
## Decision Drivers
|
||||
|
||||
* Self-service registration - users shouldn't need admin to create accounts
|
||||
* Admin approval - prevent unauthorized access
|
||||
* Granular access control - different users get different applications
|
||||
* Simple to manage - single admin shouldn't be overwhelmed
|
||||
* Audit trail - know who approved whom and when
|
||||
|
||||
## Considered Options
|
||||
|
||||
1. **Authentik enrollment flow with admin approval + group-based access**
|
||||
2. **Invite-only registration (no self-service)**
|
||||
3. **Open registration with post-hoc restriction**
|
||||
|
||||
## Decision Outcome
|
||||
|
||||
Chosen option: **Option 1 - Authentik enrollment flow with admin approval + group-based access**
|
||||
|
||||
Authentik's enrollment stages allow custom registration flows. Combined with group-based application access, this provides a complete workflow:
|
||||
- Users self-register → account created but inactive/limited
|
||||
- Admin receives notification → reviews and assigns groups
|
||||
- User gets access only to applications their groups permit
|
||||
|
||||
### Positive Consequences
|
||||
|
||||
* Self-service reduces admin burden for initial registration
|
||||
* Approval step prevents unauthorized access
|
||||
* Group-based access scales well as applications grow
|
||||
* Full audit log of approvals
|
||||
* Can add MFA requirement during enrollment
|
||||
|
||||
### Negative Consequences
|
||||
|
||||
* Admin must actively monitor registration requests
|
||||
* Users experience delay between registration and access
|
||||
* Requires proper group/application mapping setup
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ REGISTRATION FLOW │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ User │───▶│ Enrollment │───▶│ Account │───▶│ Pending │ │
|
||||
│ │ Requests │ │ Form │ │ Created │ │ Approval │ │
|
||||
│ └──────────┘ └──────────────┘ └──────────────┘ └──────┬───────┘ │
|
||||
│ │ │
|
||||
│ ┌────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────┐ │
|
||||
│ │ Admin Reviews │ │
|
||||
│ │ (Email/Dashboard) │ │
|
||||
│ └──────────┬──────────┘ │
|
||||
│ │ │
|
||||
│ ┌─────────────┼─────────────┐ │
|
||||
│ │ │ │ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ Reject │ │ Approve │ │ Approve │ │
|
||||
│ │ │ │ Basic │ │ Full │ │
|
||||
│ └──────────┘ └────┬─────┘ └────┬─────┘ │
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ homelab- │ │ homelab- │ │
|
||||
│ │ guests │ │ users │ │
|
||||
│ └──────────┘ └──────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ APPLICATION ACCESS BY GROUP │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ homelab-admins │ │
|
||||
│ │ All applications + Authentik admin + Grafana admin │ │
|
||||
│ └─────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ homelab-users │ │
|
||||
│ │ Affine, Kavita, Nextcloud, Immich, Kasm, ntfy, Vaultwarden │ │
|
||||
│ └─────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ homelab-guests │ │
|
||||
│ │ Kavita only │ │
|
||||
│ └─────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ pending-approval │ │
|
||||
│ │ No applications (can only access Authentik profile) │ │
|
||||
│ └─────────────────────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Group Structure
|
||||
|
||||
| Group | Purpose | Applications |
|
||||
|-------|---------|--------------|
|
||||
| `homelab-admins` | Full administrative access | All + Gitea, Flux UI, Authentik admin |
|
||||
| `homelab-users` | Trusted users (family) | Affine, Immich, Kasm, Kavita, Nextcloud, ntfy, Vaultwarden |
|
||||
| `homelab-guests` | Limited access (friends) | Kavita only |
|
||||
| `pending-approval` | Newly registered, not yet vetted | None (Authentik profile only) |
|
||||
|
||||
## Application Access Matrix
|
||||
|
||||
External applications exposed via `envoy-external` gateway:
|
||||
|
||||
| Application | admins | users | guests | pending |
|
||||
|-------------|--------|-------|--------|---------|
|
||||
| Authentik (admin) | ✅ | ❌ | ❌ | ❌ |
|
||||
| Authentik (profile) | ✅ | ✅ | ✅ | ✅ |
|
||||
| Affine | ✅ | ✅ | ❌ | ❌ |
|
||||
| Gitea | ✅ | ❌ | ❌ | ❌ |
|
||||
| Immich | ✅ | ✅ | ❌ | ❌ |
|
||||
| Kasm | ✅ | ✅ | ❌ | ❌ |
|
||||
| Kavita | ✅ | ✅ | ✅ | ❌ |
|
||||
| Nextcloud | ✅ | ✅ | ❌ | ❌ |
|
||||
| ntfy | ✅ | ✅ | ❌ | ❌ |
|
||||
| Vaultwarden | ✅ | ✅ | ❌ | ❌ |
|
||||
| Flux UI | ✅ | ❌ | ❌ | ❌ |
|
||||
|
||||
## Implementation
|
||||
|
||||
### Step 1: Create Groups
|
||||
|
||||
In Authentik Admin → Directory → Groups, create:
|
||||
|
||||
1. **homelab-admins**
|
||||
- Superuser status: Yes (for Authentik admin)
|
||||
|
||||
2. **homelab-users**
|
||||
- Superuser status: No
|
||||
|
||||
3. **homelab-guests**
|
||||
- Superuser status: No
|
||||
|
||||
4. **pending-approval**
|
||||
- Superuser status: No
|
||||
- This is the default group for new registrations
|
||||
|
||||
### Step 2: Create Enrollment Flow
|
||||
|
||||
In Authentik Admin → Flows & Stages:
|
||||
|
||||
#### 2a. Create Stages
|
||||
|
||||
1. **enrollment-invitation-check** (Invitation Stage)
|
||||
- Continue without invitation: Yes
|
||||
|
||||
2. **enrollment-user-form** (Prompt Stage)
|
||||
- Fields: username, email, name, password, password_repeat
|
||||
|
||||
3. **enrollment-user-write** (User Write Stage)
|
||||
- Create users as inactive: No
|
||||
- Group: `pending-approval`
|
||||
|
||||
4. **enrollment-user-login** (User Login Stage)
|
||||
- Session duration: default
|
||||
|
||||
#### 2b. Create Flow
|
||||
|
||||
1. **Name:** `homelab-enrollment`
|
||||
2. **Slug:** `homelab-enrollment`
|
||||
3. **Designation:** Enrollment
|
||||
4. **Bind stages in order:**
|
||||
- enrollment-invitation-check
|
||||
- enrollment-user-form
|
||||
- enrollment-user-write
|
||||
- enrollment-user-login
|
||||
|
||||
### Step 3: Configure Application Policies
|
||||
|
||||
For each application, create a policy binding that requires group membership:
|
||||
|
||||
#### 3a. Create Group Membership Policies
|
||||
|
||||
In Authentik Admin → Policies:
|
||||
|
||||
**Policy: require-homelab-users**
|
||||
```python
|
||||
# Expression Policy
|
||||
return ak_is_group_member(request.user, name="homelab-users") or \
|
||||
ak_is_group_member(request.user, name="homelab-admins")
|
||||
```
|
||||
|
||||
**Policy: require-homelab-guests-or-higher**
|
||||
```python
|
||||
# Expression Policy
|
||||
return ak_is_group_member(request.user, name="homelab-guests") or \
|
||||
ak_is_group_member(request.user, name="homelab-users") or \
|
||||
ak_is_group_member(request.user, name="homelab-admins")
|
||||
```
|
||||
|
||||
**Policy: require-homelab-admins**
|
||||
```python
|
||||
# Expression Policy
|
||||
return ak_is_group_member(request.user, name="homelab-admins")
|
||||
```
|
||||
|
||||
#### 3b. Bind Policies to Applications
|
||||
|
||||
For each application in Applications → Applications:
|
||||
|
||||
| Application | Policy to Bind |
|
||||
|-------------|----------------|
|
||||
| Affine | require-homelab-users |
|
||||
| Gitea | require-homelab-admins |
|
||||
| Immich | require-homelab-users |
|
||||
| Kasm | require-homelab-users |
|
||||
| Kavita | require-homelab-guests-or-higher |
|
||||
| Nextcloud | require-homelab-users |
|
||||
| ntfy | require-homelab-users |
|
||||
| Vaultwarden | require-homelab-users |
|
||||
| Flux UI | require-homelab-admins |
|
||||
|
||||
### Step 4: Admin Notification
|
||||
|
||||
Since no SMTP is configured (per ADR-0016), admin notification options:
|
||||
|
||||
#### Option A: Dashboard Monitoring
|
||||
|
||||
1. Periodically check Authentik Admin → Directory → Users
|
||||
2. Filter by group: `pending-approval`
|
||||
3. Review and move to appropriate group
|
||||
|
||||
#### Option B: Webhook to Discord/Slack (Future Enhancement)
|
||||
|
||||
Configure Authentik event to send webhook on user creation:
|
||||
|
||||
```python
|
||||
# Event Rule: new-user-notification
|
||||
# Trigger: Model Created (User)
|
||||
# Action: Webhook to Discord
|
||||
|
||||
webhook_url = "https://discord.com/api/webhooks/..."
|
||||
message = f"New user registration: {model.username} ({model.email})"
|
||||
```
|
||||
|
||||
### Step 5: Approval Process
|
||||
|
||||
When a new user registers:
|
||||
|
||||
1. Admin receives notification (or checks dashboard)
|
||||
2. Admin reviews user information:
|
||||
- Do I know this person?
|
||||
- What access level should they have?
|
||||
3. Admin action:
|
||||
- **Approve as user:** Remove from `pending-approval`, add to `homelab-users`
|
||||
- **Approve as guest:** Remove from `pending-approval`, add to `homelab-guests`
|
||||
- **Reject:** Delete user account
|
||||
4. User can now access their permitted applications
|
||||
|
||||
## User Experience
|
||||
|
||||
### Registration Flow (User Perspective)
|
||||
|
||||
1. User visits `https://auth.daviestechlabs.io/if/flow/homelab-enrollment/`
|
||||
2. Fills out registration form (username, email, password)
|
||||
3. Account created, logged in automatically
|
||||
4. Sees Authentik user dashboard with no applications
|
||||
5. Message displayed: "Your account is pending approval"
|
||||
6. After admin approval, applications appear on dashboard
|
||||
|
||||
### Custom Pending Message
|
||||
|
||||
Create a custom user interface text in Authentik:
|
||||
|
||||
In Admin → Flows → Default Interface → Customization:
|
||||
|
||||
```html
|
||||
<!-- For users with no app access -->
|
||||
<div class="pending-notice">
|
||||
<h3>Account Pending Approval</h3>
|
||||
<p>Your registration is being reviewed. You'll receive access to applications once approved.</p>
|
||||
<p>Contact the homelab admin if you need expedited access.</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
## MFA Enforcement
|
||||
|
||||
See [ADR-0030: MFA and Yubikey Strategy](0030-mfa-yubikey-strategy.md) for MFA configuration details.
|
||||
|
||||
## Audit Trail
|
||||
|
||||
Authentik logs all changes:
|
||||
|
||||
- User creation (with registration timestamp)
|
||||
- Group membership changes (who approved, when)
|
||||
- Application access attempts (granted/denied)
|
||||
|
||||
View in Admin → Events → Logs
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Rate Limiting
|
||||
|
||||
- Enrollment flow should have rate limiting to prevent spam registrations
|
||||
- Configure in Flow settings or via reverse proxy
|
||||
|
||||
### Account Cleanup
|
||||
|
||||
- Periodically review `pending-approval` group
|
||||
- Delete accounts that have been pending > 30 days without approval
|
||||
|
||||
### Group Escalation
|
||||
|
||||
- Only `homelab-admins` can modify group memberships
|
||||
- Consider requiring MFA for admin actions
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
1. **Email notifications** - When SMTP is configured, notify users of approval
|
||||
2. **Invitation codes** - Pre-approve specific registrations with invite links
|
||||
3. **Self-service group requests** - Users can request access to additional apps
|
||||
4. **Time-limited access** - Guest access expires after N days
|
||||
5. **Application-specific approval** - Per-app access requests
|
||||
|
||||
## References
|
||||
|
||||
* [Authentik Flows Documentation](https://docs.goauthentik.io/docs/flow/)
|
||||
* [Authentik Policies](https://docs.goauthentik.io/docs/policies/)
|
||||
* [Authentik Groups](https://docs.goauthentik.io/docs/user-group-role/groups/)
|
||||
339
decisions/0030-mfa-yubikey-strategy.md
Normal file
339
decisions/0030-mfa-yubikey-strategy.md
Normal file
@@ -0,0 +1,339 @@
|
||||
# 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**
|
||||
```python
|
||||
# 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**
|
||||
```python
|
||||
# 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**
|
||||
|
||||
```bash
|
||||
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`:
|
||||
|
||||
```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`:
|
||||
|
||||
```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
|
||||
|
||||
* [Authentik WebAuthn Documentation](https://docs.goauthentik.io/docs/flow/stages/authenticator_webauthn/)
|
||||
* [Vaultwarden 2FA Configuration](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-WebAuthn-authentication)
|
||||
* [WebAuthn Specification](https://www.w3.org/TR/webauthn-2/)
|
||||
* [FIDO Alliance](https://fidoalliance.org/)
|
||||
* [Yubico Developer Program](https://developers.yubico.com/)
|
||||
Reference in New Issue
Block a user