How best to Reset a Password

What is the most secure way to help a User reset his/her Password if it is forgotten?

For my Access Control (?), I am storing Passwords using a Salt, Pepper, and then Hash.

Right now, I just have the User enter his/her e-mail, then I e-mail a Temporary Password with a link to “log_in.php”

Now that I have re-tooled my Log-In system to use hashing, I am uncertain how to approach things?

For example, when I receive a User’s E-mail, do I create a new Salt and Temporary Password, and then create a new Temporary Hash and e-mail the Temporary Password to the User?

I have always felt it was hokey to e-mail a Password to someone claiming they forgot their Password and just requiring an E-mail address as verification?! (What is to stop someone who hacked into your e-mail or a friend or colleague from re-setting your passowrd for you unsuspectingly?!)

Anyways, I think I have a pretty secure Log-In system and I just want to be certain that my +password_rset.php" script is NOT the “weak link”?!

Thanks,

Debbie

the way I’ve always done it is a temporary pw field that hold the temp pw. on the login authentication, i check if it’s the real or temp pass and let them in. regardless of which one was used,.clear out the temp pass field.

obviously if security is important, then you should ask a personal question as well, like secret answer or dob or something

Well, it really depends.

Often times email is the only authentication you have.

If you got a security question at registration, you can also use that.

If you have some other means of verification, use that as well (if reasonable).

An email address reset password link is often good enough, but it depends on what you have available.

As for what to actually do with the password data itself, I would recreate it the same way you create a password for a new user. In theory there is little reason to create a new salt, but it can’t hurt.

Here is my workflow…

[INDENT]- User clicks (Forgot Password?) link

  • User is taken to “Reset Password” form and asked for E-mail
  • User enters E-mail and clicks “Reset Password”
  • System looks up E-mail in database
  • System generates a Temporary Password
	$tempPass = substr(sha1(uniqid(mt_rand(), true)), 3, 10);
  • System generates a Temporary Salt
	$tempSalt = substr(sha1(uniqid(mt_rand(), true)), 0, 10);

-System generates a Temporary Hash

	$tempHash = hash_hmac('sha512', $tempPass . $tempSalt, VINEGAR);
  • System finds User based on E-mail entered
  • System updates Member table with new Hash (i.e. Password)
  • System sends e-mail with new Temporary Password and a link to Log In
  • User copies Temporary Password
  • User clicks on Log In link
  • User enters E-mail and pastes in Temporary Password
  • System logs in User
  • System redirects User to “Change Password” form
  • User enters E-mail, Temporary Password, New Password, Confirms New Password
  • System changes Password
  • System redirects User to index.php
    [/INDENT]

It probably seems more involved that what it is, but what do you think?

Debbie

in the scenario you’ve just outlined, suppose user A has a strong password that she really likes

user B, being pernicious, enters user A’s email address in the reset password form

user A then receives an email forcing her to log in with a temporary password, just to be able to reset her password to what it was before

can you see the flaw here?

the temporary password has to be just that, temporary

the email that gets sent out with the temporary password should say “if you did not request the password change, simply ignore this email”

I agree with r937. It’s not a temporary password if it’s the only password stored in the database. :wink:

Aside from that, your process looks fairly standard and should be just about as secure as anything else out there.

Sorry, haven’t eaten in a day and low on brain cells…

So, you are saying I should create - as I believe someone else said earlier - a “temp_password” field and store it there?

There if Debbie’s favorite password was “r937IsMyHero” and samanime - being the devil he is :wink: - reset my password, then…

1.) I could either still log in with “r937IsMyHero” or
2.) I could log in with “SomeTemporaryPassword” maybe for some predetermined time period like 12 hours

Is that what you mean?

Debbie

Well, it is “temporary” from the standpoint that the User will likely re-set it to something memorable shortly thereafter.

Aside from that, your process looks fairly standard and should be just about as secure as anything else out there.

Ugh! You guys are making the last part of my User Accounts module hard!! (:

If given a choice, would you prefer (from a security standpoint)…

1.) Challenge Questions

2.) E-mailed Temporary Password

Debbie

#2 should occur regardless, #1 is a choice you must make based on whether it’s that important (and be honest with yourself).

I don’t think you understood me…

I was saying that if someone forgot their password, could I…

Scenario #1:

  • Ask for their E-mail
  • Ask a Challenge Question
  • Have them do a Change Password on the spot (with no E-mail)

Scenario #2:

  • Ask for their E-mail
  • E-mail a Temporary Password
  • Have them Log In using the Temporary Password
  • Force them to do a Change Password

The point being, “Which is more secure and reliable in establishing the User is the User? A confirmed E-mail or a Correctly Answered Challenge Question??”

Or to go crazy…

Scenario #3:

  • Ask for their E-mail
  • Ask a Challenge Question
  • If correct Challenge Answer, then E-mail a Temporary Password
  • Have them Log In using the Temporary Password
  • Force them to do a Change Password

Follow me?

Debbie

Challenge questions can be troublesome, especially if they don’t remember their answer.

I’d stick with the email solution, unless this is for some top secret government site… in which case I recommend biometric scanning and DNA analysis to confirm identity. :wink:

With your temporary password, you say it’s temporary… but it’s not. If someone hits that and puts in someone else’s email, and that person doesn’t go through their email to change their password, that “temporary” password stays until they do. A temporary password should expire after a little while (like 10-30 minutes).

Weren’t the G-man sunglasses a dead give-away?! :cool:

With your temporary password, you say it’s temporary… but it’s not. If someone hits that and puts in someone else’s email, and that person doesn’t go through their email to change their password, that “temporary” password stays until they do. A temporary password should expire after a little while (like 10-30 minutes).

So what do I have to do to re-tool my current code? :frowning:

I posted my current workflow in Post #4.

Can you please edit that workflow so I can better understand what you are recommending?

Is it as simple as just storing the “Temporary Password” and “Temporary Hash” that my script creates in a new “temp_pass” and “temp_hash” fields in my Members table, and then somehow checking for EITHER the <Current Password> OR the <Temp Password> during Log In?

(My Create Account, Log In, Change Password, and now Reset Password got a lot more complicated this past week now that I am “Salting”, “Peppering” and “Hashing” User’s Passwords…)

Thanks,

Debbie

  1. User enters email address
  2. System generates a random string.
  3. Store this new string in a temporary password field and in another field, put current time
  4. Email the password to the user.
  5. User goes to log in page and logs in, with either password (their real one or the temporary).
  6. If it’s temporary, check the expiration time - if they pass redirect them and tell them to update their password. If it’s their real password - treat it as a normal login.
  7. Delete the temporary password field and timestamp

How does my site know whether the original “real” password or the new “temporary” password was entered?

Debbie

Here’s a rough code explanation

$row = db_query("SELECT salt,real_password,temp_password,temp_password_timestamp FROM member WHERE username = '$user_entered_username'");

if ($row['real_password'] == password($user_entered_password,$row['salt'])) {
   # real password used, login ok
} else if ($row['temp_password'] == password($user_entered_password,$row['salt']) {
    if (time() <= $row['temp_password_timestamp '] + $password_valid_time) {
        # temp password  and log in ok
    } else {
        # temp password but expired, different error message
    }
} else {
    # login failed
}

Rather than coding real vs temporary into your system, with more DB fields and complexity, why not wait until the reset action is confirmed by the user through their email.

It shouldn’t be possible for me to reset someone else’s password just by typing their email address.

IMO a system like this should email the user (similar to what r937 suggested) giving them a link to change it, or the option to ignore it (keeping the existing PW).

So the flow might be:

  • Enter email address on reset PW page
  • User is emailed a link back to your site with a token allowing them to enter a new PW
  • If they ignore the link, or don’t submit the PW nothing happens.
  • They have to specify the new password, which might help automatic temp ones being forgotten.

Yes, it’s only as secure as their email, but so are most things.

Thanks for the suggestions.

While I really appreciate everyone’s help, I am feeling exasperated because I have spent the entire day and night working on this dumb “reset_password.php” script, and people’s suggestions make me keep changing directions and I’m exhausted… :frowning:

If you could help me out a little more it would be greatly appreciate! (Although since it is past 2:00a.m. here, I don’t know how much longer I’ll last…)

Questions:

1.) So you are saying just have one Hash and one Salt field like originally?

2.) Sorry to say, but what exactly is a “token”?

3.) How do I create a “token”?

4.) Is that secure compared to me e-mailing a “Temporary password”?

5.) Can you help me figure out how to do that, please?

Here is what I have now. Everything is working with one “hitch”…

  • User clicks on “(Forgot Password?)” link
  • System takes User to “Reset Password” page
  • User enters Email
  • System find Salt for the Email
  • System generates a Temporary Password
  • System Hashes Temporary Password and stores in Temporary Password Field with Timestamp
  • System emails Temporary Password
  • User opens Email and copies Temporary Password
  • User clicks on link in email to “Log In” page
  • System displays 'Log In" page
  • User enters Email and some Password
  • System determines if Password matches either Original Password or Temporary Password
  • System logs in User
  • System redirects to “Change Password” page

I am having a problem here, because I prompt for…

[INDENT]* Email

  • Current Password
  • New Password
  • Confirm New Password
    [/INDENT]
    …and I just realized that my script needs to be intelligent enough to know whether the “Current Password” is the Original Password or the Temporary Password?! :blush:

I think you way sounds much easier, and would like to try it - if it is SECURE - and if you can help a bit?!

Thanks,

Debbie