Treat reset links as one-time recovery grants
Generate a high-entropy token, store only its hash, bind it to an account and purpose, expire it, and consume it once. Return uniform request responses and avoid changing the account until the holder confirms on a safe page. OWASP Forgot Password Cheat Sheet supplies the primary specification or operating model for this decision.
Protect reset consumption from scanners and retries
Link scanners may visit URLs automatically, so GET displays a confirmation step and POST consumes the token. Decide whether a new request invalidates older links. After success, invalidate recovery grants and offer or require session revocation according to risk. Ory account recovery documentation provides the complementary protocol or operational detail.
Model recovery as states
Store a hash of the reset token with account, purpose, created time, expiry, attempt count, and consumed time. A GET request may display confirmation but must not consume the grant because email security scanners visit links automatically. Consume it only on the password-changing POST, in the same transaction that updates credential state.
Choose and document whether a new request invalidates earlier grants. Uniform request responses limit account enumeration, while per-account and network controls slow abuse. Logs should contain a grant identifier or hash prefix, never the token.
Resolve concurrent and post-reset behavior
Two submissions with the same link must have one winner. The loser receives an expired-or-used result without learning more account state. After success, invalidate remaining recovery grants, notify the account through an independent channel, and apply the product’s documented session policy. Ory Kratos provides self-service account recovery and management flows as described in the Ory recovery documentation.
Test scanner GET, expired token, two active links, simultaneous POSTs, password-policy rejection, and a database failure during consumption. Start by drawing the state machine and adding a concurrency test that proves password update and one-time consumption cannot diverge.
Sources are linked throughout this guide. Product capabilities can change; consult the linked documentation for your deployment.
Read our editorial approach ↗