Appearance
Auth Architecture
Status: Design locked in. Implementation ships in Phase 5 (post-AWS).
Three auth paths
| Path | Who | Factors | When |
|---|---|---|---|
| Tier 1 — Agent magic link | Pending-review and pre-activation agents | Email magic link (single factor) | Phase 5 |
| Tier 2 — Agent multi-factor | Activated agents with access to member data | Magic link + TOTP (authenticator app) | Phase 6, gated pre-leads |
| Super-admin | Taha (platform owner) only | Password (argon2id) + TOTP + IP allowlist | Phase 5 |
Tier 1 — Onboarding (low friction)
For agents who just signed up and are in pending_review status. They can complete their profile, take the discovery survey, and see their status. They cannot see any member data.
- Factor: email magic link only. 15-minute token TTL. Single use.
- Session: 15-minute idle timeout, 8-hour absolute maximum.
- Cookie: HTTP-only, Secure, SameSite=Lax, opaque token indexed in
agent_sessions. - Rate limit: 5 failed login attempts per email per hour, then exponential backoff.
Sessions expire on the strict 15/8 profile even at Tier 1 so that we operate at CMS EDE Appendix A § 9 standards from day one rather than tighten later under audit pressure.
Tier 2 — Post-activation (true multi-factor)
True multi-factor authentication per NIST 800-63B requires two different factor types. Email magic link is "something you have: email access." Email OTP on top is the same factor — not real MFA.
The correct pattern:
- Primary factor: Magic link via email (something you have: email access)
- Second factor: TOTP via authenticator app — different device, different factor class
- Fallback: 10 single-use recovery codes generated at TOTP setup
- Setup: When an admin activates an agent, the agent must set up TOTP on next login before reaching any member data routes. QR code + manual key, save recovery codes, confirm one TOTP code.
This matches HealthSherpa's auth pattern (username/password + TOTP) and satisfies CMS EDE MFA requirements.
What Tier 2 gates
- Member PII (names, addresses, SSN tails, DOB)
- Lead queue (incoming pre-filled applications)
- Enrollment workflows and carrier submission
- Compensation data and book of business
Why not SMS as second factor
NIST 800-63B (rev 3) deprecates SMS OTP for AAL2+ due to SIM-swap attacks. We skip SMS entirely. If users request it later, we can add a passkey/WebAuthn option — the auth module is designed so this is a drop-in extension.
Super-admin — separate credential path
Super-admin operations (adding/removing other admins, compliance queries, break-glass recoveries) are rare and catastrophic if compromised. Separating the super-admin auth path entirely from the regular agent/admin flow is the same pattern as AWS root vs IAM users: you almost never log in as root.
Super-admin design
- Route:
/sa-login— obscure, not linked from anywhere. Returns 404 unless hitting from an allowlisted IP (CloudFront/WAF layer, before the app ever sees the request). - Factor 1 — Knowledge: strong password, stored as argon2id hash in
super_adminscollection (single row initially). Managed in password manager. - Factor 2 — Possession: TOTP via authenticator app (same pattern as Tier 2).
- Factor 3 — Location: IP allowlist enforced at the WAF. Recommendation: Taha uses Tailscale with an exit node, or paid static-IP VPN. Add that exit IP to the allowlist.
- Session: 5-minute idle, 1-hour absolute maximum. Very short. Re-auth required for every management action.
- Separate session cookie: different cookie name, different encryption key from the agent/admin session cookie. Prevents session confusion attacks.
- Only reachable from
/super-admin/*— separate middleware tree. Super-admin routes have no access to day-to-day admin workflows and vice versa.
What super-admin does
- Add, remove, change role of entries in the
adminscollection - Run compliance exports and audit log queries
- Execute break-glass DB writes during DR scenarios
Break-glass for lost super-admin access
- TOTP lost: recovery codes (kept in password manager) still work from an allowlisted IP.
- Phone and IP both lost (travel + device reset):
scripts/admin/reset-super-admin.jsrequires direct MongoDB write URI (itself gated behind AWS Secrets Manager). Resets TOTP secret + IP allowlist. Writes audit log entry automatically. - Bootstrap:
scripts/admin/seed-super-admin.jsruns once at production setup. Validates collection is empty, sets password hash + TOTP + IP, writes audit entry, exits.
Critical security fix: duplicate NPN handling
The threat: without protection, someone who knows another agent's NPN could "re-sign up" with their own email, receive a magic link to their email, and hijack the account.
The mitigation: when POST /api/agents/onboarding sees a duplicate NPN or email:
- DO NOT send the magic link to the email that was just submitted.
- DO send the magic link to the email already on file for that NPN.
- Response to the user: "If an account exists with that NPN or email, we've sent a login link to the email on file." — never confirms or denies existence.
- Log the attempt (NPN, submitted email, IP, userAgent) in
agent_audit_logfor fraud monitoring. - Rate-limit these attempts to prevent NPN enumeration.
Same pattern on the /agent-login page — never confirm whether an email is registered.
Email change flow (legitimate email updates)
NPN is the immutable primary identifier. Email is mutable via a verification flow:
- Agent logs in with current email (magic link to current email).
- Goes to Account Settings → "Change email address."
- Enters new email.
- System sends verification magic link to the NEW email with "confirm email change" wording.
- Agent clicks link from new inbox. Old email receives a simultaneous notification ("Your email is being changed to X") — if unauthorized, old-email owner sees it.
- On new-email confirmation: update
agents.email, invalidate all existing sessions (force re-login on all devices), writeagent_audit_logentry with old → new email. - Old email remains in audit log forever; log is append-only.
Session requirements (CMS EDE Appendix A § 9)
- Unique user ID per agent (enforced via unique NPN + unique email)
- 15-minute idle timeout, 8-hour absolute max (both Tier 1 and Tier 2)
- Re-authentication required for sensitive actions (viewing member SSN, running exports, changing admin roles)
- All auth events logged to
agent_audit_log: actor, action, resource, timestamp, IP, userAgent, outcome - Failed login attempts rate-limited (5 per email per hour, then exponential backoff)
- Session revocation on email change, role change, or admin revocation
Audit logging — every auth event
Every auth and admin event writes to agent_audit_log. See Data Models for schema. Retention: 6 years minimum (HIPAA), 10 years preferred (EDE-safer).
Events logged:
onboarding_submitted— new waitlist submissionmagic_link_requested/magic_link_consumed/magic_link_expiredtotp_setup_started/totp_setup_completed/totp_challenge_succeeded/totp_challenge_failedlogin_succeeded/login_failed/login_rate_limitedlogout_manual/session_expired_idle/session_expired_maxemail_change_initiated/email_change_confirmedstatus_changed(admin action on agent) — with before/after roleadmin_role_granted/admin_role_revoked(super-admin action)break_glass_script_run— which script, by which OS user, when
Files (to be created in Phase 5)
src/lib/
agent-auth.ts # createMagicLink, verifyMagicLink, session CRUD, isAdmin, isSuperAdmin
agent-totp.ts # setup, verify, recovery code generation
agent-audit.ts # helper called from every write/auth event
agent-rate-limit.ts # in-memory for MVP, Redis later
src/app/api/agents/auth/
request/route.ts # POST magic link for returning agents (rate-limited)
verify/route.ts # GET magic-link callback, sets session cookie
logout/route.ts # POST, clears cookie
totp/setup/route.ts # POST, generates TOTP secret + QR code
totp/verify/route.ts # POST, confirms TOTP code during setup or login
totp/recovery/route.ts # POST, use a recovery code
src/app/api/super-admin/auth/
login/route.ts # IP-gated, password + TOTP
verify/route.ts # consume TOTP challenge
logout/route.ts
src/middleware.ts # session gating for /agent-dashboard, /agent-discovery, /admin/*, /super-admin/*Related
- Compliance Model — how this auth design satisfies SOC 2 / HIPAA / EDE
- Data Models —
agents,admins,super_admins,agent_sessions,agent_audit_logschemas - Overview — how this fits into the phase roadmap