Recovery and operations

Build password recovery

Create an enumeration-resistant reset flow with hashed single-use tokens, normal password policy, session invalidation, and user notification.

8 minute lesson

~~~

Password recovery is an alternate authentication path and is often the easiest route around a strong login system.

Return the same request response for existing and unknown accounts, generate a short-lived token, store its hash, and apply the normal password hashing policy on reset. Do not automatically log the user in afterward; revoke existing sessions and notify the account owner.

Keep the public request path deliberately boring:

POST /forgot-password
→ "If an account exists, we sent instructions."

The status, body, and approximate timing should be similar whether the address exists. Still rate-limit by account and network signals. A generic response prevents easy enumeration; it does not make an unlimited email-sending endpoint safe.

The reset token should be random, short-lived, single-use, and bound to one user and one purpose. Store its hash rather than the raw value. When the user submits a new password, consume the token and replace the password hash atomically. If either operation can commit alone, concurrent requests can reuse the same link.

Build the link from a configured or allowlisted canonical HTTPS origin, never an untrusted Host header. Keep third-party scripts off the reset page, send Referrer-Policy: no-referrer, and make sure request logs do not capture token-bearing query strings. Replace the visible URL after the server has accepted the token.

Do not weaken the normal password policy during recovery, and do not send a new password by email. After success, revoke the user’s existing sessions so a thief who already has a session cannot remain signed in. Let the user log in normally, and send a notification that explains how to report an unexpected reset without including secrets.

Operational failures need explicit behavior. If the email provider is down, avoid claiming that a message was sent while silently dropping the request. Record a safe delivery job or return a retryable generic result without exposing whether the account exists.

Test unknown and known addresses, an altered host header, expired and reused tokens, two concurrent reset submissions, password replacement, session invalidation, delivery failure, and notifications. A good integration test proves the old password and every old session stop working after the transaction commits.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →