I'm using a pretty standard way of cookie login - I give the user two cookies, one with his username and the other with a randomly generated string plus a user-specific salt.
This is what happens at login:
$_SESSION['username']=$row[username];
$_SESSION['user_id']=$row['id'];
$loginhash=generateRandomBase64String()."_".$row['salt'];
$number_of_days = 14;
$date_of_expiry = time() + 60 * 60 * 24 * $number_of_days ;
setcookie( "userlogin", $row['username'], $date_of_expiry, "/" ) ;
setcookie( "loginhash", $loginhash, $date_of_expiry, "/" ) ;
$cryptedhash=crypt($loginhash);
$today=date("Y-m-d");
mysql_query("update members set last_login='$today',loginhash='$cryptedhash' where id='$row[id]' ") or die(mysql_error());
So the $loginhash
value is something like Pe0vFou8qe++CqhcJgFtRmoAldpuIs+d_g5oijF76
and the crypted version of that is stored in the database. The salt is already in the database, as it's generated for each user when they sign up.
I use session variables ($_SESSION[username]
) to keep users logged in. Then, when a user visits the site, I check for two things: if $_SESSION[username]
is not set but $_COOKIE[userlogin]
is, I check if the hash is correct so I could log the user in. The problem is, the hash is never correct.
if($_COOKIE['userlogin'] && !isset($_SESSION[user_id])){
$username=mysql_real_escape_string($_COOKIE['userlogin']);
$loginhash=mysql_real_escape_string($_COOKIE['loginhash']);
$salt=substr($loginhash,-8);
$result=mysql_query("select * from members where (username='$username' || email='$username') && salt='$salt' limit 1 ") or die (mysql_error());
$row=mysql_fetch_assoc($result);
$cryptedhash=$row['loginhash'];
if (crypt($loginhash, $cryptedhash) == $cryptedhash){
$_SESSION['username']=$row[username];
$_SESSION['user_id']=$row['id'];
}
}
$_COOKIE[userlogin]
is the correct value. When I check for the username/salt combination in the database, the correct result is found (echo $row[username]
gives correct value). However, the if
condition below that is never met. I would think there's something weird about my PHP configuration, but I use the same crypting mechanism to store passwords and there it works properly.
So can anyone see what's going wrong here?
PS I'm not looking to start a discussion about cookie safety or the variety of available hashing functions here.