Skip to content

fix(auth): harden forgot-password for production Resend email#181

Merged
seanhanca merged 2 commits into
mainfrom
fix/email-resend-forgetpassword
Mar 6, 2026
Merged

fix(auth): harden forgot-password for production Resend email#181
seanhanca merged 2 commits into
mainfrom
fix/email-resend-forgetpassword

Conversation

@seanhanca
Copy link
Copy Markdown
Contributor

@seanhanca seanhanca commented Mar 4, 2026

Summary

The forgot-password / reset-password flow is fully implemented but won't work in Vercel production due to Resend email configuration gaps. This PR hardens the flow for production readiness.

  • Rate limiting: Add IP-based rate limiting (3 req / 15 min) to the forgot-password endpoint to prevent email bombing
  • Production error logging: Log structured errors when email send fails in production (previously silent); dev mode still logs token/URL to console
  • Reset redirect: Reduce post-reset redirect delay from 3s → 1.5s (auth cookie is already set by the API)
  • Startup validation: Warn at cold-start if RESEND_API_KEY is missing or EMAIL_FROM still uses the sandbox @resend.dev domain
  • Documentation: Document required Resend production setup in .env.example (custom domain verification, DNS records, env vars)

Required Vercel env vars for production

Variable Purpose
RESEND_API_KEY Resend API key (resend.com/api-keys)
EMAIL_FROM Sender address on a verified custom domain (e.g. NaaP <noreply@naap.io>) — the default onboarding@resend.dev is sandbox-only
NEXT_PUBLIC_APP_URL Production URL used in the reset link

The sender domain must have SPF, DKIM, and optionally DMARC DNS records configured in Resend.

Test plan

  • Trigger forgot-password locally — verify token URL logged to console
  • Send 4+ requests for the same IP — verify 429 response on the 4th
  • Complete full reset-password flow — verify password updated and session cookie set
  • Deploy to Vercel with RESEND_API_KEY + verified domain → verify email received
  • Remove RESEND_API_KEY → verify structured error logged at startup and on send

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Email configuration validation now runs at startup to identify setup issues.
    • Forgot-password endpoint now includes rate limiting to manage request frequency.
  • Bug Fixes

    • Password reset redirect now completes faster (reduced from 3000ms to 1500ms).
  • Documentation

    • Enhanced email configuration guidance for production-grade domain verification and DNS setup.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 503b3c70-2fe3-44c1-9367-607104216c82

📥 Commits

Reviewing files that changed from the base of the PR and between 8e6f6ef and e9a9db8.

📒 Files selected for processing (6)
  • .env.example
  • apps/web-next/src/app/(auth)/reset-password/reset-password-form.tsx
  • apps/web-next/src/app/api/v1/auth/forgot-password/route.ts
  • apps/web-next/src/lib/api/auth.ts
  • apps/web-next/src/lib/email.ts
  • apps/web-next/src/lib/rateLimit.ts

📝 Walkthrough

Walkthrough

This PR enhances the password reset flow with rate limiting on the forgot-password endpoint, adds email configuration validation at startup, updates environment documentation for production email setup, and refines post-reset redirect timing and logging behavior.

Changes

Cohort / File(s) Summary
Email Configuration & Documentation
.env.example, apps/web-next/src/lib/email.ts
Updated EMAIL_FROM documentation with production guidance on domain verification and DNS configuration. Added new validateEmailConfig() function that checks for RESEND_API_KEY presence and validates EMAIL_FROM domain at startup, with different logging behavior for production vs. non-production environments.
Rate Limiting
apps/web-next/src/lib/rateLimit.ts, apps/web-next/src/app/api/v1/auth/forgot-password/route.ts
Introduced new forgotPassword rate limiter configuration (3 requests per 15 minutes per IP). Applied rate limiting middleware to forgot-password POST handler with early return on limit exceeded.
Password Reset Flow & Logging
apps/web-next/src/app/(auth)/reset-password/reset-password-form.tsx, apps/web-next/src/lib/api/auth.ts
Reduced post-reset redirect delay from 3000ms to 1500ms with clarifying comments. Changed requestPasswordReset logging to emit errors in production and token/URL details only in non-production environments.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

size/L

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main objective: hardening the forgot-password flow for production Resend email.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/email-resend-forgetpassword

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread plugins/service-gateway/frontend/src/pages/ConnectorWizardPage.tsx Outdated
@seanhanca seanhanca force-pushed the fix/email-resend-forgetpassword branch from 9401514 to a273d72 Compare March 4, 2026 20:22
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Mar 4, 2026

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

Project Deployment Actions Updated (UTC)
naap-platform Ready Ready Preview, Comment Mar 6, 2026 6:04pm

Request Review

@github-actions github-actions Bot added size/M Medium PR (51-200 lines) scope/shell Shell app changes and removed size/M Medium PR (51-200 lines) labels Mar 4, 2026
@seanhanca seanhanca requested a review from eliteprox March 4, 2026 20:22
…livery

Production deployment of forgot-password requires:
- RESEND_API_KEY set in Vercel env vars
- EMAIL_FROM set to an address on a verified custom domain in Resend
  (default onboarding@resend.dev is sandbox-only, sends only to account owner)
- DNS records configured: SPF, DKIM, and optionally DMARC for the sender domain
- NEXT_PUBLIC_APP_URL set to the production URL (used in reset link)

Changes:
- Add IP-based rate limiting (3 req/15min) to forgot-password endpoint
- Log structured errors in production when email send fails (was silent)
- Keep dev-mode console logging of reset token/URL for local testing
- Reduce reset-password redirect delay from 3s to 1.5s (cookie already set)
- Add startup validation warning if RESEND_API_KEY missing or EMAIL_FROM
  still uses sandbox @resend.dev domain
- Document Resend production setup steps in .env.example

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@seanhanca seanhanca force-pushed the fix/email-resend-forgetpassword branch from a273d72 to 6629393 Compare March 4, 2026 21:03
@github-actions github-actions Bot added the size/M Medium PR (51-200 lines) label Mar 4, 2026
Copy link
Copy Markdown
Contributor

@eliteprox eliteprox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

@eliteprox
Copy link
Copy Markdown
Contributor

@seanhanca Do you need any help setting up the resend api key or dns records?

@seanhanca seanhanca merged commit eba4f55 into main Mar 6, 2026
24 of 25 checks passed
@seanhanca seanhanca deleted the fix/email-resend-forgetpassword branch March 6, 2026 20:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope/shell Shell app changes size/M Medium PR (51-200 lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants