Prompt
How do I send a password reset email from a backend API?
Latest observation
Oct 5, 2026
ChatGPT
A secure password-reset flow usually looks like this:
- User requests reset
POST /auth/forgot-password
{ "email": "user@example.com" }
- Backend generates a random, single-use token
- Use a cryptographically secure random generator.
- Store a hash of the token in your database, not the raw token.
- Give it a short expiration, e.g. 15–30 minutes.
- Invalidate previous reset tokens.
- Send the email
Include a link such as:
https://yourapp.com/reset-password?token=<token> - User submits a new password
POST /auth/reset-password
{
"token": "...",
"password": "new-password"
}
- Backend validates the token Check that it exists, hasn't expired, and hasn't been used. Then hash the new password with Argon2id or bcrypt and update the account.
- Invalidate the token and existing sessions This prevents the reset link from being reused.
Important security details
- Return the same response whether the email exists or not, e.g. “If an account exists, we sent a reset email.” This prevents account enumeration.
- Rate-limit reset requests by IP and account/email.
- Don't put the user's password or other sensitive data in the URL.
- Don't log reset tokens.
- Use HTTPS.
- Consider invalidating all active sessions after a successful password reset.
For the email provider, your backend can call an email API such as Resend, SendGrid, or Amazon SES. The basic architecture is:
Browser
│
│ POST /forgot-password
▼
Backend ── generate token ──► Database
│
│ send email
▼
Email provider
│
▼
User clicks reset link
│
▼
Backend ── validate token ──► Database
│
└── hash new password + invalidate token
If you tell me your backend stack (e.g. Node/Express, Python/FastAPI, Django, Laravel, Rails, Go, or Java/Spring), I can give you a complete implementation.