Skip to content

feat(auth): password reset and email confirmation - #19

Merged
TheGeniusOfEternity merged 2 commits into
mainfrom
feat/email-flows
Sep 29, 2026
Merged

TheGeniusOfEternity merged 2 commits into
mainfrom
feat/email-flows

Conversation

@TheGeniusOfEternity

Copy link
Copy Markdown
Owner

Stacked on #18 (it builds on the account page and auth changes there). Branch auto-delete is now on, so this PR retargets to main when #18 merges.

Summary

Password reset and email confirmation, with email delivery that can be switched on later.

Email delivery (server/src/lib/mailer.ts)

  • RESEND_API_KEY + EMAIL_FROM set: sends through the Resend HTTP API (no SDK dependency).
  • Not set, development: prints the email (with the link) to the server log.
  • Not set, production: disabled. GET /api/auth/features returns { email: false } and the UI hides "Forgot password?" and "Send email".

Tokens: new AuthToken table (migration is additive: one nullable column on User plus a new table). Only the SHA-256 hash is stored; tokens are single-use and expire (reset 1 h, confirmation 24 h); issuing one invalidates earlier unused tokens of the same type. Links put the token in the URL hash so it never reaches server logs, analytics or Referer headers.

Flows

  • POST /api/auth/forgot-password: same response whether or not the email exists.
  • POST /api/auth/reset-password: sets the password, revokes every session, marks the email verified.
  • Sign-up sends a confirmation email (a mail failure doesn't fail sign-up); POST /api/auth/verify-email; POST /api/auth/resend-verification from the account page. Users created via Yandex start verified.
  • The client email language follows the UI locale.

Vercel: the five new endpoints go through one function, api/auth-resource.ts, plus a rewrite. api/ now has 10 of the 12 Hobby functions.

Client: /forgot-password, /reset-password, /verify-email pages (shared AuthCard), "Forgot password?" on sign-in, a success notice after a reset, email status and resend on /account. Verification is idempotent per token and the hash is read StrictMode-safely.

To enable in production

  1. Buy a domain, add it in Resend, add the DNS records.
  2. Set RESEND_API_KEY and EMAIL_FROM="WidgeCode <noreply@your-domain>" in Vercel.
  3. Redeploy (the migration runs automatically).

Test plan

  • Local end-to-end with the console transport: sign-up confirmation email (RU), link confirms, token removed from the URL; "Forgot password?" → email → new password → redirect to sign-in with notice; old password 401, new 200, reusing the link 400; email marked verified
  • Server: 10 flow tests (enumeration, token type/reuse/expiry, session revocation, sign-up survives mail failure, resend rules) and 4 mailer tests
  • Client: forgot/reset/verify pages (incl. StrictMode single request), account resend
  • format:check, lint, typecheck, test (44 client + 48 server), build, typecheck:api

- AuthToken model + migration (hashed, single-use, expiring tokens) and
  User.emailVerifiedAt; Yandex-created users start verified
- Mailer: Resend HTTP API when RESEND_API_KEY/EMAIL_FROM are set, console
  in development, disabled in production otherwise (GET /auth/features)
- POST /auth/forgot-password (no account enumeration), /reset-password
  (revokes all sessions, verifies email), /verify-email,
  /resend-verification; sign-up sends a confirmation email
- Endpoints routed through api/auth-resource.ts to stay within the
  Vercel Hobby function limit
- Client: forgot/reset/verify pages (tokens in URL hash, StrictMode-safe),
  forgot link on sign-in, email status and resend on the account page
@vercel

vercel Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
widgecode Ignored Ignored Preview Sep 29, 2026 7:18pm UTC

Base automatically changed from feat/error-pages-and-account-linking to main September 29, 2026 19:19
@TheGeniusOfEternity
TheGeniusOfEternity merged commit 4fef923 into main Sep 29, 2026
3 checks passed
@TheGeniusOfEternity
TheGeniusOfEternity deleted the feat/email-flows branch September 29, 2026 19:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant