Adam Johns
Adam Johns

Reputation: 36373

Password Reset Backend Functionality

I'm having a little trouble with how to conceptually handle password resets if a user forgets their password. I have been trying to model my system after this SO answer.

Here is my current setup:

  1. The user clicks forgot password link on page
  2. The page prompts them to enter their email address
  3. The user enters email address and hits "Send me my info"
  4. When the user hits "Send my my info" a new entry is created in my password_change_requests table with a random id, a time, and the user's username.
  5. I send the user a link that is in the format http://mysite.net/resetpassword.php?id=xxx&username=yyy
  6. The resetpassword.php file GETs the id and username
  7. resetpassword.php checks for a row in password_change_requests that has username and a time that is not yet expired
  8. If row is found, then make sure the id from get matches hashed id in that row.
  9. If the id is validated then echo html with forms and buttons for entering new password
  10. Try to send new password to a different php script that verifies new password and confirm new password match. verifyNewPassword.php

My design must be flawed somehow because I can't figure out how to send the user back to resetpassword.php if the passwords don't match in verifyNewPassword.php. I can't just give them a link to click sending them back to resetpassword.php, because that link also needs the id and username from GET. I tried sending that GET data from resetpassword.php to verifyNewPassword.php, but I can't figure it out since the html is inside an echo. Here is a summary of my code:

resetpassword.php:

if ($tokenFound) {
    echo "<html>
<body>
<h1>Password Reset</h1>
<form action='verifyNewPassword.php' method='post'>
<input type='password' name='password' placeholder='New Password'><br>
<input type='password' name='confirmpassword' placeholder='Confirm New Password'><br><br>
<input type='submit' value='Reset Password'>
</form>

</body>
</html>";
  }
  else {
    //notify user token is expired or not found. try to reset password again
    echo "not a valid token";
  }

verifyNewPassword.php:

if ($password != $confirmpassword) {
    print "Passwords don't match. Click <a href=\"resetpassword.php\">here</a> to try again.<br/>";
  }
  else {
    echo "passes match";
  }

Upvotes: 2

Views: 3022

Answers (2)

Adam Johns
Adam Johns

Reputation: 36373

I ended up passing the id and username values from resetpassword to verify password like so:

if ($tokenFound) {
    echo '<html>
<body>
<h1>Password Reset</h1>
<form action="verifyNewPassword.php" method="post">
<input type="password" name="password" placeholder="New Password"><br>
<input type="password" name="confirmpassword" placeholder="Confirm New Password"><br><br>
<input type="hidden" name="username" value="' . $username . '">
<input type="hidden" name="id" value="' . $id . '">
<input type="submit" value="Reset Password">
</form>

</body>
</html>';
  }
  else {
    //notify user token is expired or not found. try to reset password again
    echo "not a valid token";
  }

Upvotes: 0

lc.
lc.

Reputation: 116538

Any way you write this, you will need these xxx and yyy values in verifyNewPassword.php. The best solution would save these in hidden inputs when passed to resetpassword.php, send them along with the POSTed values, and verify them one more time from verifyNewPassword.php.

If you want to avoid the link, you can send a 303 response with the Location header set to http://mysite.net/resetpassword.php?id=xxx&username=yyy, with another optional flag set if you wanted to display an error message.

Upvotes: 1

Related Questions