Recovery and operations
Verify email ownership
Confirm that a user controls an email address with a short-lived single-use token without granting more authority than verification requires.
8 minute lesson
An email address should not be treated as verified merely because signup accepted its syntax.
Generate a strong random token, store only its hash with purpose and expiry, send the raw token in one HTTPS link, and consume it once. Rate-limit resends and return generic responses that do not reveal account existence.
Treat verification as a narrowly scoped capability. A token created to verify an email must not also reset a password, sign a user in, or approve an email change. Store enough state to enforce that boundary:
token_hash | user_id | target_email | version | purpose | expires_at | consumed_at
Hashing the token protects users if this table leaks: the raw value exists only in the email and the browser request. On redemption, look up the hash, verify the exact target address, current version, purpose, and expiry, then mark the token consumed and that address verified in one transaction. Two simultaneous clicks should not both succeed.
An email-change flow needs an additional decision. Confirming the new address proves control of that address, but it does not prove the request came from the account owner. Require a recent authenticated session before starting the change, notify the old address, and increment the pending-address version when it changes. Define resend policy explicitly: either keep earlier links valid until expiry or atomically invalidate them when issuing the new token.
Links also leak through logs, analytics, referrers, and support screenshots. Avoid third-party scripts on the redemption page, never log query strings containing tokens, and replace the URL after consuming it.
Implement the request and consume endpoints, then test expiration, replay, simultaneous redemption, resend invalidation, and changing the pending email before redemption. The final assertion should check the exact authority granted: only the intended address becomes verified.
Lesson completed