- Added ADR-0016: Affine email verification strategy - Moved ADRs 0019-0024 from docs/adr/ to decisions/ - Renamed to consistent format (removed ADR- prefix)
151 lines
5.5 KiB
Markdown
151 lines
5.5 KiB
Markdown
# Affine Email Verification Strategy for Authentik OIDC
|
|
|
|
* Status: proposed
|
|
* Date: 2026-02-04
|
|
* Deciders: Billy
|
|
* Technical Story: Affine requires email verification for users, but Authentik is not configured with SMTP for email delivery
|
|
|
|
## Context and Problem Statement
|
|
|
|
Affine (self-hosted note-taking/collaboration tool) requires users to have verified email addresses. When users authenticate via Authentik OIDC, Affine checks the `email_verified` claim. Currently, Authentik has no SMTP configuration, so it cannot send verification emails, causing new users to be blocked or have limited functionality in Affine.
|
|
|
|
How can we satisfy Affine's email verification requirement without adding significant infrastructure complexity to the homelab?
|
|
|
|
## Decision Drivers
|
|
|
|
* Minimize external dependencies and ongoing costs
|
|
* Keep the solution self-contained within the homelab
|
|
* Avoid breaking changes on Affine upgrades
|
|
* Maintain security - don't completely bypass verification for untrusted users
|
|
* Simple to implement and maintain
|
|
|
|
## Considered Options
|
|
|
|
1. **Override `email_verified` claim in Authentik** - Configure Authentik to always return `email_verified: true` for trusted users
|
|
2. **Deploy local SMTP server (Mailpit)** - Run a lightweight mail capture server in-cluster
|
|
3. **Configure Affine to skip verification for OIDC users** - Use Affine's configuration to trust OIDC-provided emails
|
|
|
|
## Decision Outcome
|
|
|
|
Chosen option: **Option 1 (Override `email_verified` claim)** as the primary solution, with Option 3 as a fallback if Affine supports it.
|
|
|
|
This approach requires zero additional infrastructure, works immediately, and is appropriate for a homelab where all users are trusted (family/personal use). Option 2 (Mailpit) is documented for future reference if actual email delivery becomes needed for other applications.
|
|
|
|
### Positive Consequences
|
|
|
|
* No additional services to deploy or maintain
|
|
* Works immediately with existing Authentik setup
|
|
* No external dependencies or costs
|
|
* Can be easily reverted if requirements change
|
|
|
|
### Negative Consequences
|
|
|
|
* Bypasses "real" email verification - relies on trust
|
|
* If Affine is ever exposed to untrusted users, this would need revisiting
|
|
* Other applications expecting real email verification would need similar workarounds
|
|
|
|
## Pros and Cons of the Options
|
|
|
|
### Option 1: Override `email_verified` Claim in Authentik
|
|
|
|
Configure an Authentik property mapping to always return `email_verified: true` in the OIDC token for the Affine application.
|
|
|
|
**Implementation:**
|
|
1. In Authentik Admin → Customization → Property Mappings
|
|
2. Create a new "Scope Mapping" for email_verified
|
|
3. Set expression: `return True`
|
|
4. Assign to Affine OIDC provider
|
|
|
|
* Good, because zero infrastructure required
|
|
* Good, because immediate solution
|
|
* Good, because appropriate for trusted homelab users
|
|
* Bad, because not "real" verification
|
|
* Bad, because per-application configuration needed
|
|
|
|
### Option 2: Deploy Local SMTP Server (Mailpit)
|
|
|
|
Deploy Mailpit (or MailHog) as a lightweight SMTP server in the cluster that captures all emails for viewing via web UI.
|
|
|
|
**Implementation:**
|
|
```yaml
|
|
# Example Mailpit deployment
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: mailpit
|
|
namespace: productivity
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: mailpit
|
|
template:
|
|
spec:
|
|
containers:
|
|
- name: mailpit
|
|
image: axllent/mailpit:latest
|
|
ports:
|
|
- containerPort: 1025 # SMTP
|
|
- containerPort: 8025 # Web UI
|
|
```
|
|
|
|
Then configure Authentik SMTP settings:
|
|
- Host: `mailpit.productivity.svc.cluster.local`
|
|
- Port: `1025`
|
|
- TLS: disabled (internal traffic)
|
|
|
|
* Good, because provides actual email flow for testing
|
|
* Good, because useful for other apps needing email (password reset, notifications)
|
|
* Good, because emails viewable via web UI
|
|
* Bad, because emails don't actually leave the cluster
|
|
* Bad, because another service to maintain
|
|
* Bad, because requires Authentik reconfiguration
|
|
|
|
### Option 3: Configure Affine to Skip Verification for OIDC Users
|
|
|
|
If Affine supports it, configure the application to trust email addresses from OIDC providers without requiring separate verification.
|
|
|
|
**Potential Configuration (needs verification):**
|
|
```yaml
|
|
# In affine-config ConfigMap
|
|
AFFINE_AUTH_OIDC_EMAIL_VERIFIED: "true"
|
|
# or similar environment variable
|
|
```
|
|
|
|
* Good, because no Authentik changes needed
|
|
* Good, because scoped to Affine only
|
|
* Bad, because may not be supported by Affine
|
|
* Bad, because could break on Affine upgrades
|
|
* Bad, because requires research into Affine's configuration options
|
|
|
|
## Implementation Notes
|
|
|
|
### For Option 1 (Recommended)
|
|
|
|
1. Access Authentik admin at `https://auth.daviestechlabs.io/if/admin/`
|
|
2. Navigate to Customization → Property Mappings
|
|
3. Create new Scope Mapping:
|
|
- Name: `Affine Email Verified Override`
|
|
- Scope name: `email`
|
|
- Expression:
|
|
```python
|
|
return {
|
|
"email": request.user.email,
|
|
"email_verified": True,
|
|
}
|
|
```
|
|
4. Edit the Affine OIDC Provider → Advanced Settings → Scope Mappings
|
|
5. Replace default email mapping with the new override
|
|
|
|
### Future Considerations
|
|
|
|
If the homelab expands to include external users or applications requiring real email delivery:
|
|
- Revisit Option 2 (Mailpit) for development/testing
|
|
- Consider external SMTP service (SendGrid free tier, AWS SES) for production email
|
|
|
|
## References
|
|
|
|
* [Authentik Property Mappings Documentation](https://docs.goauthentik.io/docs/property-mappings)
|
|
* [Affine Self-Hosting Documentation](https://docs.affine.pro/docs/self-host-affine)
|
|
* [Mailpit GitHub](https://github.com/axllent/mailpit)
|