Prompt
How to send password reset emails
Latest observation
Sending password reset emails is a standard flow where you generate a secure, short-lived token, email it to the user, and verify it when they click the link. This ensures account recovery without exposing sensitive data.
🔑 Core Flow
Generate reset token
Use a cryptographically secure random string (UUID, JWT, or crypto.randomBytes).
Store a hashed version in your database with expiry (e.g., 10–15 minutes).
Send reset email
Use a transactional email API (Resend, Postmark, SendGrid, Mailgun).
- Keep the subject simple: “Password Reset Request”.
Include a link like:
Code
https://yourapp.com/reset-password?token=XYZ
- Provide clear instructions: “Click the link to reset your password. This link expires in 15 minutes.”
Verify token
When the user clicks, check expiry and whether it’s already used.
If valid, allow them to set a new password.
Mark token as used immediately after reset.
Update password
Hash the new password with bcrypt or Argon2.
Store securely in your database.
Invalidate all active sessions for that user.
⚠️ Security Best Practices
Expire tokens quickly (10–15 minutes).
Allow only one active reset token per user.
Rate-limit reset requests to prevent abuse.
Never reveal whether an email exists in your system (always respond with “If this email is registered, you’ll receive a reset link”).
Use HTTPS everywhere.
✅ Example (Node.js + Express + Resend API)
js
const crypto = require("crypto");
const axios = require("axios");
app.post("/request-reset", async (req, res) => {
const token = crypto.randomBytes(32).toString("hex");
const hashedToken = hash(token); // store hashed version
await saveTokenToDB(req.body.email, hashedToken, Date.now() + 15601000);
await axios.post("https://api.resend.com/emails", {
- from: "no-reply@yourdomain.com",
- to: req.body.email,
- subject: "Password Reset Request",
- text:
Click here to reset: https://yourapp.com/reset-password?token=${token}
}, {
- headers: { Authorization:
Bearer ${process.env.RESEND_API_KEY}}