Security: gate sessions on verified email (opt-in) #53

Merged
justin merged 1 commits from security-require-email-verification into main 2026-06-09 11:22:56 -04:00
Owner

Backlog §2.10: registration issued a live session and email_verified_at was written but never read — unverified users had full access and there was no switch to require verification.

Adds REQUIRE_EMAIL_VERIFICATION (default false). When true:

  • resolve_session_user returns None for an unverified user — the single read-side gate over every authed request, incl. the session minted at registration.
  • login raises 403 instead of issuing a useless token.

Default false on purpose: self-hosts without SMTP and pre-existing accounts (email_verified_at null) must not be locked out; operators flip it on once mail works and accounts are verified. Documented in .env.example.

Tests: default-off unchanged; on → register session 401, login 403, then verify → both work. 75 passed.

🤖 Generated with Claude Code

Backlog §2.10: registration issued a live session and `email_verified_at` was written but never read — unverified users had full access and there was no switch to require verification. Adds `REQUIRE_EMAIL_VERIFICATION` (**default false**). When true: - `resolve_session_user` returns None for an unverified user — the single read-side gate over every authed request, incl. the session minted at registration. - `login` raises **403** instead of issuing a useless token. Default false on purpose: self-hosts without SMTP and pre-existing accounts (`email_verified_at` null) must not be locked out; operators flip it on once mail works and accounts are verified. Documented in `.env.example`. Tests: default-off unchanged; on → register session 401, login 403, then verify → both work. **75 passed.** 🤖 Generated with [Claude Code](https://claude.com/claude-code)
justin added 1 commit 2026-06-09 11:22:55 -04:00
Backlog §2.10: registration issued a live session and email_verified_at was
written but never read, so an unverified user had full access and there was no
switch to require verification.

Add REQUIRE_EMAIL_VERIFICATION (default false). When true:
- resolve_session_user returns None for a user whose email_verified_at is null —
  the single read-side gate covering every authenticated request, incl. the
  session minted at registration.
- login raises 403 ("email not verified") instead of issuing a useless token.

Default false on purpose: self-hosts without SMTP, and accounts created before
this gate existed (email_verified_at null), must not be locked out. Operators
enable it once mail works and accounts are verified. Documented in .env.example.

Tests: default-off keeps unverified accounts working; on → register's session
won't resolve (401), login is 403, and after verify-email both work. 75 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Justin Paul <justin@jpaul.me>
justin merged commit 39e3eac3df into main 2026-06-09 11:22:56 -04:00
justin deleted branch security-require-email-verification 2026-06-09 11:22:56 -04:00
Sign in to join this conversation.