Password Reset Best Practices for 2026
Password reset is one of the most critical, and most attacked, parts of any authentication system. Get it wrong, and you've opened a backdoor into user accounts. Get it right, and you've built trust with your users.
Here's what we've learned building password reset infrastructure at scale.
1. Never Trust Email Alone
Email-only password reset is vulnerable to account takeover if someone gains access to a user's inbox. Add a second factor:
- Email + SMS code: Send a 6-digit code to their phone number
- Email + Security questions: Not recommended (weak security)
- Email + Time-based lockout: Require users to wait 24 hours before completing reset
The best approach depends on your threat model. For most apps, email + SMS provides the right balance of security and UX.
2. Rate Limit Everything
Attackers will try to:
- Enumerate your user database by requesting resets for every email
- Brute force verification codes
- Spam users with reset requests
Implement rate limiting at multiple layers:
// Per email: 3 requests per hour
// Per IP: 10 requests per hour
// Per account: Lock after 5 failed verification attempts
This prevents abuse while allowing legitimate users to retry if needed.
3. Use Short-Lived Tokens
Reset tokens should expire quickly. We recommend:
- 15 minutes for password reset links
- 5 minutes for 2FA codes
- 30 minutes for magic links
Shorter windows reduce the attack surface. If a user's email is compromised, the attacker has less time to act.
4. Hash Everything
Never store verification codes in plaintext. Use bcrypt with appropriate rounds:
- Passwords: 12 rounds (slow, high security)
- Verification codes: 10 rounds (fast enough for real-time verification)
This protects users even if your database is breached.
5. Prevent Enumeration
Don't reveal whether an email exists in your system. Always return:
{
"success": true,
"message": "If that email exists, we sent a reset link."
}
Use timing-safe comparisons and add dummy operations to ensure response times are identical for existing/non-existing emails.
6. Log Everything
Audit logs are critical for:
- Detecting abuse patterns
- Investigating security incidents
- Compliance (GDPR, SOC 2)
Log: email (hashed), timestamp, IP, success/failure, session ID. Never log plaintext passwords or codes.
Conclusion
Password reset is deceptively complex. Most teams underestimate the security considerations and end up with vulnerable implementations.
That's why we built ResetKit, to handle all of this for you. Our infrastructure includes rate limiting, enumeration protection, bcrypt hashing, and audit logging out of the box.
Want to see it in action? Start a free trial and integrate in 15 minutes.