Got a strange one here.
I'm using a function to generate a random string of chars for a token :
private static function generatePasswordResetCode()
{
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-';
return substr(str_shuffle($chars), 0, RESET_TOKEN_LENGTH);
}
RESET_TOKEN_LENGTH
is a constant :
define("RESET_TOKEN_LENGTH", 100);
The code is saved to the table like so :
$code = self::generatePasswordResetCode();
$expiry_timestamp = time() + RESET_CODE_EXPIRY_TIME;
$sql = "INSERT INTO reset_codes (code, user_id, expires_at)
VALUES (:code, :user_id, :expires_at)";
$db = static::getDB();
$stmt = $db->prepare($sql);
$stmt->bindParam(':user_id', $id, PDO::PARAM_INT);
$stmt->bindParam(':code', $code, PDO::PARAM_STR);
$stmt->bindValue(':expires_at', date('Y-m-d H:i:s', $expiry_timestamp), PDO::PARAM_STR);
$stmt->execute();
In the database the code
column is set to varchar(255)
. I've also tried text
and I have the same problem either way.
Whatever I define RESET_TOKEN_LENGTH
to be up to and including 63 chars everything works fine, but any number above that and the string is being truncated in the code
column :
define("RESET_TOKEN_LENGTH", 63);
// results in
MFYflHL6bVwNEG1DpqRA0ry5TgC9KhmntPUao2x-ujvekX7sZcQizWSd43OBIJ8
Great, but...
define("RESET_TOKEN_LENGTH", 64);
// results in
7fITjSp32gmA0YJCwFhrWvPk4VDQMZonl19btBKs5Ri-zULeXO...
Any ideas what could be causing this?
**** UPDATE ****
So this doesn't appear to be MySQL related but PHP related instead.
It seems that the combination of substr
& str_shuffle
result in a limit of 63 chars no matter what number above 63 you define.
To test it I changed the function like so :
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-';
$code = substr(str_shuffle($chars), 0, RESET_TOKEN_LENGTH);
$code2 = substr(str_shuffle($chars), 0, RESET_TOKEN_LENGTH);
$code = $code . $code2;
return $code;
Which results in the correct var_dump
output :
define("RESET_TOKEN_LENGTH", 50);
//results in
string(100) "fk8DcbusUeVxWOdp1HwNLEy9gzYm6tq0o3PMaZAIh2Sn45F-K7GH9l18hZNk73j6cQpFDfPwxMCe4BTrqiIASdRs5WEnoKgmzyXY"
Where as doing :
define("RESET_TOKEN_LENGTH", 64);
//results in
string(126) "Q14Hd0WJjVotYRfsaU5pAM7DeZSuvwnCmxqbPgh6839XrEIyBcKTONzG-kil2FL0LUgQG8452WqKEfdmuzHlr9PZevc7VhnNCSjbk-wTyMR1iOspxaXYJDoFtBIA36"
Showing that $code
and $code2
are being truncated to 63 chars.
How very strange!
** UPDATE 2 **
It seems my lack of understanding as to how str_shuffle
works was at fault here and nothing else. See the accepted answer below.