- 0029: User registration workflow with approval and group-based access - 0030: MFA and Yubikey strategy for Authentik and Vaultwarden
341 lines
16 KiB
Markdown
341 lines
16 KiB
Markdown
# 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/)
|