← All writing

Generate a public reset-token value with random_bytes

PHP 8.3+Sources checked 2026-09-13

A timestamp, sequential ID, or shuffled email address is a poor basis for a secret token. An attacker should not be able to infer the next token from a previous request. Use the cryptographic randomness API and choose an encoding suitable for transport.

Generate bytes, then encode them

<?php
$token = bin2hex(random_bytes(32));
assert(strlen($token) === 64);
assert(ctype_xdigit($token));

The hexadecimal string is longer than the original byte sequence; that is an encoding tradeoff, not additional entropy. If the randomness source fails, let the operation fail. Do not fall back to rand() to keep the request moving.

Issuing is not the whole lifecycle

For a reset flow, store a hash of the token, an expiry, the intended account, and enough state to make successful consumption single use. Compare the submitted token through the appropriate verification logic and expire it after use. Prefer the framework's tested reset implementation for a conventional account reset.

URLs may appear in logs and browser history. Avoid putting unrelated account secrets alongside the token, and ensure the reset page does not leak it through third-party requests. Token generation itself does not provide rate limiting or account authorization.

Test expired, already-used, malformed, and unrelated-account tokens. A length assertion like the standalone example checks representation only. It is not a statistical proof of randomness or an integration test of your reset endpoint. The important application assertion is that an invalid or reused token cannot change credentials.

Reference

Official documentation. The examples here illustrate the stated boundary; adapt them to your application and test its failure paths.