Content · Web Development · PHP

PHP Password Reset Flow with Expiring Tokens

Issue a random one-time reset token, store only its digest, and enforce expiration and atomic.

1 views Published Oct 17, 2026 Updated Oct 17, 2026 admin

Issue a random one-time reset token, store only its digest, and enforce expiration and atomic consumption.

The examples introduce the underlying control before showing a verification and an application-level safeguard.

What You Will Build


Issue a random one-time reset token, store only its digest, and enforce expiration and atomic consumption.

Prerequisites


Use PHP 8.4 or newer, HTTPS for all authentication operations, and an application session or database where required. Example configuration values are placeholders, never production secrets.

Example 1: Basic Operation


Generate a one-time, random reset token and retain only its hash in storage.

<?php
$rawToken = bin2hex(random_bytes(32));
$tokenHash = hash('sha256', $rawToken);
$expiresAt = time() + 20 * 60;
// Store only $tokenHash and $expiresAt in the database; email $rawToken.
echo strlen($rawToken);

Example 2: A Different Use Case


Validate the token format before a database lookup.

<?php
$rawToken = $_POST['token'] ?? '';
if (!is_string($rawToken) || !preg_match('/^[a-f0-9]{64}$/D', $rawToken)) {
    http_response_code(400); exit;
}
$lookup = hash('sha256', $rawToken);
// Look up $lookup in a transactional database operation.

Practical Example: Checking the Result


Ensure consumption and password change are one atomic, one-time operation.

<?php
$newPassword = $_POST['new_password'] ?? '';
if (!is_string($newPassword) || strlen($newPassword) < 12) { http_response_code(400); exit; }
$newHash = password_hash($newPassword, PASSWORD_DEFAULT);
// Inside a database transaction, SELECT the matching unexpired token FOR UPDATE.
// Update the user's hash and mark the token consumed in the same transaction.
// Check that exactly one row was affected; then commit and revoke old sessions.
// The complete flow must use database locking and anti-enumeration responses.

Important Behavior and Edge Cases


Avoid account enumeration; lock or transactionally consume tokens and revoke old sessions when the password changes.

Enforce controls on the server, test denial paths and do not assume that a snippet alone implements an entire production workflow.

Comparison with Related Functions


ApproachKey distinction
PHP Password Reset Flow with Expiring TokensIssue a random one-time reset token, store only its digest, and enforce expiration and atomic consumption.
Related techniqueEmail verification links and password-reset links require different actions and scopes.

Common Beginner Mistakes


MistakeCorrect approach
Confusing this operation with a neighboring cryptographic or security mechanismEmail verification links and password-reset links require different actions and scopes.
Ignoring a security prerequisite or failure caseAvoid account enumeration; lock or transactionally consume tokens and revoke old sessions when the password changes.

Key Takeaways


  • Issue a random one-time reset token, store only its digest, and enforce expiration and atomic consumption.
  • Avoid account enumeration; lock or transactionally consume tokens and revoke old sessions when the password changes.
  • Email verification links and password-reset links require different actions and scopes.

Apply this behavior to a real application only after confirming the required extension, configuration and failure handling on the deployment runtime.

Share this resourceSend this page to someone who may find it useful.