Forgot Password Script not Working

Hi all,

I am trying to get a Password reminder script to work, which I took from a tutorial I found online.. Here is the tutorial

I'm working off my WAMP localhost. I have  2 tables in my database.

Table 1 - users -  This is the existing table with user information which I created
Fields: uid, password, uemail, name

Table 2 - recovery_keys - This is the table created as part of the tutorial.
Fields: rid, userID, token, valid

The page consists of a basic form page with one field and a submit button (and an area where a message is displayed if the email input is not successful).  The code for the page is as follows:
<?php
include ('config.php');
include ('function.php');
include ('database.php');
if(isset($_POST['submit']))
{
	$uemail = $_POST['uemail'];
	$uemail = mysqli_real_escape_string($db, $uemail);
	if(checkUser($uemail) == "true") //check user is a function defined in function.php
	{
		$userID = UserID($uemail);
		$token = generateRandomString();
		
		$query = mysqli_query($db, "INSERT INTO recovery_keys (userID, token) VALUES ($userID, '$token') ");
		if($query)
		{
			 $send_mail = send_mail($uemail, $token);

			if($send_mail === 'success')
			{
				 $msg = 'A mail with recovery instruction has sent to your email.';
				 $msgclass = 'bg-success';
			}else{
				$msg = 'There is something wrong - Failed at this point.';  //THIS IS THE MESSAGE I GET WHEN I ENTER AN EMAIL
				$msgclass = 'bg-danger';
		

Open in new window



When I enter an email address which corresponds to an email address which is in the  database I get the message saying - There is something wrong - Failed at this point. I guess this means there is a problem here -  $send_mail = send_mail($uemail, $token);

The original form looked like this
<form class="form-horizontal" role="form" method="post">
			    <h2>Forgot Password</h2>

				<?php if(isset($msg)) {?>
                    <div class="<?php echo $msgclass; ?>" style="padding:5px;"><?php echo $msg; ?></div>
                <?php } ?>

                <p>
                    Forgot your password? No problem, we will fix it. Just type your email below and we will send you password recovery instruction to your email. Follow easy steps to get back to your account.
                </p>
    
                <div class="row">
                    <div class="col-lg-12">
                    <label class="control-label">Your Email</label>
                    </div>
                </div>
    
                <div class="row">
                    <div class="col-lg-12">
                        <input class="form-control" name="uemail" type="email" placeholder="Enter your email here..." required>
                    </div>
                </div>
    
                <div class="row">
                    <div class="col-lg-12">
                        <button class="btn btn-success btn-block" name="submit" style="margin-top:8px;">Submit</button>
                    </div>
                </div>
			</form>

Open in new window


I thought an issue might be with there being no form action so I added :

<form action="<?php echo ('index.php'); ?>" method="post">
			    <h2>Forgot Password</h2>

Open in new window

But this didn't change things from what I could see.

The functions used are as follows:
<?php


function checkUser($uemail)
{
	global $db;
	
	$query = mysqli_query($db, "SELECT uid FROM users WHERE uemail = '$uemail'");

	if(mysqli_num_rows($query) > 0)
	{
		return 'true';
	}else
	{
		return 'false';
	}
}

function UserID($uemail)
{
	global $db;
	
	$query = mysqli_query($db, "SELECT uid FROM users WHERE uemail = '$uemail'");
	$row = mysqli_fetch_assoc($query);
	
	return $row['uid'];
}


function generateRandomString($length = 20) {
	// This function has been taken from stackoverflow.com
    
	$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return md5($randomString);
}

function send_mail($to, $token)
{
	require 'PHPMailer/PHPMailerAutoload.php';
	
	$mail = new PHPMailer;
	
	$mail->isSMTP();
	$mail->Host = 'smtp.gmail.com';
	$mail->SMTPAuth = true;
	$mail->Username = 'henryswanson2018@gmail.com';
	$mail->Password = 'XXXXXX'; //I'm guessing my password goes here?
	$mail->SMTPSecure = 'ssl';
	$mail->Port = 465;
	
	$mail->From = 'henryswanson2018@gmail.com';
	$mail->FromName = 'Henry Swanson';
	$mail->addAddress($to);
	$mail->addReplyTo('henryswanson2018@gmail', 'Reply');
	
	$mail->isHTML(true);
	
	$mail->Subject = 'Demo: Password Recovery Instruction';
	$link = 'forget.php?email='.$to.'&token='.$token;
	$mail->Body    = "<b>Hello</b><br><br>You have requested for your password recovery. <a href='$link' target='_blank'>Click here</a> to reset your password. If you are unable to click the link then copy the below link and paste in your browser to reset your password.<br><i>". $link."</i>";
	
	$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
	
	if(!$mail->send()) {
		return 'fail';
	} else {
		return 'success';
	}
}

function verifytoken($userID, $token)
{	
	global $db;
	
	$query = mysqli_query($db, "SELECT valid FROM recovery_keys WHERE userID = $userID AND token = '$token'");
	$row = mysqli_fetch_assoc($query);
	
	if(mysqli_num_rows($query) > 0)
	{
		if($row['valid'] == 1)
		{
			return 1;
		}else
		{
			return 0;
		}
	}else
	{
		return 0;
	}
	
}
?>

Open in new window


Lastly, I did notice that when I press submit, the recovery_keys table populates with a new token (with a userID and valid figure of 1).

Hope that makes some kind of sense. If not, I'll try to explain it in more broken down steps. Many thanks for taking the time to read this. Any advice or help would be great.

Many thanks.
AdamTrying to learn phpAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Dillyn BarberCIOCommented:
I haven't looked in depth but noticed a few things that may contribute. Also good to note, when using Gmail SMTP from a local environment or gcp/aws instance there could be roughly a 7 minute delay.

$mail->addReplyTo('henryswanson2018@gmail', 'Reply');

Open in new window

is wrong and should be removed, could be caught as spam and should only be used if different from to (will still be detected as spam or phishing if different).

Try using tls for your secure smtp and port 587 (more secure and always works) ssl and 465 should be used as a fallback. Since you are running this on your local machine you may need to check if those ports are blocked or if there are firewall rules preventing outgoing on these ports.

I say this because I am assuming you are not getting an email at all, I didn't see where you mentioned one way or the other.

You are also leaving yourself vulnerable to SQL injections by not escaping
$query = mysqli_query($db, "SELECT uid FROM users WHERE uemail = '$uemail'");
$query = mysqli_query($db, "SELECT valid FROM recovery_keys WHERE userID = $userID AND token = '$token'");

Open in new window

Etc.

I would opt to strip the whole token system you are trying to use and opt-out of MD5 for passwords as that is not a secure method either and opt to have your hashes salted with at least a SHA1.

An alternative method to entertain may be to force a 2FA (2 factor) system. On user signup require a phone number that can be texted to recover their account. Here is a quick about on that:
https://www.codementor.io/slavko/google-two-step-authentication-otp-generation-du1082vho

Hope this helps and sheds some light.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
AdamTrying to learn phpAuthor Commented:
Thanks Dillyn,

I'll look into your recommendations now. Many thanks for the information.
AdamTrying to learn phpAuthor Commented:
Thanks.

After your comments and further issues with the tutorial I was following, I'm dropping that tutorial, and moving onto another one which I have found. Already, I'm experiencing some problems with it, but I'll post about them separately.  Thanks.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Development

From novice to tech pro — start learning today.