I have recently adapted some code from http://megarush.net/forgot-password-php/ to help me create a forgot password function. I have changed it to mysqli and added some bcrypt features when updating the password. In short form, the user types in their email address, get sent a link, and this link allows them to update their password but it also gets hashed again. My problem is... I can get the email to go to the user, but when the link is clicked it keeps saying "Invalid link or Password already changed" even when trying new email addresses. Any ideas where I've gone wrong? Appreciate the help guys!
I have a token table with email
, token
, and used
.
forgot.php
<?php require 'header.php';
if (!isset($_GET['email'])) {
echo '<form action="forgot.php">
Enter Your Email Id:
<input type="text" name="email" />
<input type="submit" value="Reset My Password" />
</form>';
exit();
}
$email = $_GET['email'];
$sql = "SELECT email FROM user WHERE email='$email'";
$query = $mysqli_conn->query($sql);
if ($query->num_rows == 0) {
echo "Email id is not registered";
die();
}
$token = getRandomString(10);
$sql = "INSERT INTO `tokens` (`token`, `email`) VALUES ('{$token}','{$email}')";
$query = $mysqli_conn->query($sql);
function getRandomString($length) {
$validCharacters = "ABCDEFGHIJKLMNPQRSTUXYVWZ123456789";
$validCharNumber = strlen($validCharacters);
$result = "";
for ($i = 0; $i < $length; $i++) {
$index = mt_rand(0, $validCharNumber - 1);
$result.= $validCharacters[$index];
}
return $result;
}
function mailresetlink($to, $token) {
$subject = "Forgot Password";
$uri = 'http://' . $_SERVER['HTTP_HOST'];
$message = '
<html>
<head>
<title>Forgot Password</title>
</head>
<body>
<p>Click on the given link to reset your password <a
href="' . $uri . '/project/reset.php?token=' . $token . '">Reset Password</a></p>
</body>
</html>
';
$headers = "MIME-Version: 1.0" . "\r\n";
$headers.= "Content-type:text/html;charset=iso-8859-1" . "\r\n";
$headers.= 'From: Admin<webmaster@example.com>' . "\r\n";
$headers.= 'Cc: Admin@example.com' . "\r\n";
if (mail($to, $subject, $message, $headers)) {
echo "We have sent the password reset link to your email id <b>" . $to . "
</b>";
}
}
if (isset($_GET['email'])) mailresetlink($email, $token);
?>
reset.php
<?php require 'header.php';
$token = $_GET['token'];
if (!isset($_POST['password'])) {
$sql = "SELECT email FROM tokens WHERE token='" . $token . "' and used=0";
$query = $mysqli_conn->query($sql);
while ($row = mysqli_fetch_array($query)) {
$email = $row['email'];
}
if ($email != '') {
$_SESSION['email'] = $email;
}
else die("Invalid link or Password already changed");
}
$password = $_POST['password'];
$email = $_SESSION['email'];
if (!isset($password)) {
echo '<form method="post">
enter your new password:<input type="password" name="password" />
<input type="submit" value="Change Password">
</form>';
}
if (isset($_POST['password']) && isset($_SESSION['email'])) {
$password = password_hash($password, PASSWORD_DEFAULT);
$sql = "UPDATE user SET password= '$password' where email='$email'";
$query = mysqli_query($sql);
if ($query) mysqli_query("UPDATE tokens SET used=1 WHERE token='$token'");
echo "Your password is changed successfully";
if (!$query) echo "An error occurred";
}
?>
UPDATE: The invalid error is now fixed and the form displays, but now it just appears saying 'an error occurred'. Added sql errors in to pick up any errors, it seems to be fine until it gets to updating the password as I have echoed variables and
if (isset($_POST['password']) && isset($_SESSION['email'])) {}
comes back working