# 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)