Forgot Password: what is the best method of implementing a forgot password function?

20,907

Solution 1

  1. I personally would send an email with a link to a short term page that lets them set a new password. Make the page name some kind of UID.
  2. If that does not appeal to you, then sending them a new password and forcing them to change it on first access would do as well.

Option 1 is far easier.

Solution 2

A few important security concerns:

  • A passphrase question / answer actually lowers security since it typically becomes the weakest link in the process. It's often easier to guess someone's answer than it is a password - particularly if questions aren't carefully chosen.
  • Assuming emails operate as the username in your system (which is generally recommended for a variety of reasons), the response to a password reset request shouldn't indicate whether a valid account was found. It should simply state that a password request email has been sent to the address provided. Why? A response indicating that an email does/doesn't exist allows a hacker to harvest a list of user accounts by submitting multiple password requests (typically via an HTTP proxy like burp suite) and noting whether the email is found. To protect from login harvesting you must assure no login/auth related functions provide any indication of when a valid user's email has been entered on a login/pass reset form.

For more background, checkout the Web Application Hackers Handbook. It's an excellent read on creating secure authentication models.

EDIT: Regarding the question in your edit - I'd suggest:

"A password request email has been sent to the address you provided. If an email doesn't arrive shortly, please check your spam folder. If no email arrives, then no account exists with the email you provided."

There's a trade-off being made here between ease of use and security. You have to balance this based on context - is security important enough to you and your users to justify this inconvenience?

Solution 3

Send email with new password.

FORCE a password change when they arrive and key in the new password.

This ensures that the person who wanted the password will be the only only getting in to the account.

If the email is sniffed, someone could get in to the account (of course), but the real party will discover this immediately (as their password you just sent them doesn't work).

Also send confirmations of password changes to the users.

If someone get the new password, and then an email saying "thanx for changing the password", they're going to be rather puzzled and will talk to an admin if they didn't do it.

Solution 4

Using the email verification/password reset link will give you better security. If you look around this is how most websites do it and people are pretty used to this verification, so I'd recommend using this type of authentication.

Solution 5

I would think (gbrandt's) Option 2 would be a great method if it is combined with some personal information you already have for the user. i.e date of birth.

When the user requests a new password (reset) via entering his email address, he also has to enter a correct date of birth (or something else) before the password is reset and a new one is emailed to the user.

Only those who know him well can possibly annoy him by resetting his password! It cant be a stranger or a bot

Upon 5 or 7 bad email-address & date of birth combinations the user is emailed that his password has been requested to be reset and has failed due to an incorrect credential. Then password resetting for that account is suspended for 24hrs or any desired period.

(if too many users contact the webadmin regarding this email he'll know someone is trying to maliciously attain information from your website/app)

What do you guys think?

Share:
20,907
penetra
Author by

penetra

I am a website and web application developer in Calgary, Alberta. I have been doing backend web development in PHP and frontend in HTML/CSS/JavaScript for over 20 years. My specialties are Symfony, Vue, Event Sourcing & CQRS, Craft CMS, WordPress. I've built everything from basic basic brochure style websites to heavily trafficked eCommerce site and social platforms to internal applications.

Updated on July 15, 2022

Comments

  • penetra
    penetra almost 2 years

    I'm wondering what the best method is for creating a forgot password function on a website. I have seen quite a few out there, here are a few or combination of:

    • passphrase question / answer (1 or more)
    • send email with new password
    • on screen give new password
    • confirmation through email: must click link to get new password
    • page requiring user to enter a new password

    What combination or additional steps would you add to a forgot password function? I'm wondering about how they request the new password and how they end up getting it.

    I'm operating on the principal that the password cannot be retrieved; a new password must be given/generated.

    Edit I like what Cory said about not displaying if the username exists, but I'm wondering what to display instead. I'm thinking half the problem is that the user forgot which email address they used, which displaying some sort of "does not exist" message is useful. Any solutions?

  • William Brendel
    William Brendel about 15 years
    Option 1 also has the advantage of not being susceptible to DoS attacks on the user. For example, someone constantly clicks the "reset password" link in option 2, so the user is effectively locked out of their account. You can guard against it, but why bother? Option 1 is the way to go...
  • slikts
    slikts over 13 years
    How do you "easily guess" long randomly generated strings?
  • Jayden
    Jayden over 13 years
    My 'Option 1' reference is no longer clear with other posts - it refers to the first option presented by the OP. It referred to a suggestion of using a 'secret question' , that if answered correctly could be quessted such as 'what highschool did you attend?'. Sorry for this becoming unclear.
  • Jens Roland
    Jens Roland about 13 years
    +1 for the rare instance of sound, simple security advice. Good job.
  • corymathews
    corymathews about 13 years
    wouldn't you be able to determine if an email was already being used at sign up also?
  • Cory House
    Cory House about 13 years
    Yes, though the same approach could be used to notify existing users. The same caveats with the impact to ease of use apply.
  • Tommy
    Tommy over 12 years
    Any reason why the user should not be logged in once he/she sets a new password?
  • martinstoeckli
    martinstoeckli almost 10 years
    I had a quick look at the source but i didn't get at the code which really does the work. So i wondered about the sha-256 in the config, does this mean that the passwords are hashed with a single hash calculation or is this part of an iterated PBKDF2? Is the salt really derived from the username, instead of the random source of the operating system? How is the forgotten-password-code stored, is it stored as hash only?
  • OhadR
    OhadR almost 10 years
    the passwords are encrypted using a keystore + salt (the username). if user forgot his password, he does not get it, but instead he get an email to his inbox, so we make sure HE IS THE ONE (his identity). in the email there is an encrypted link that leads him to "set new password" page. u can try it in the demo (the link to the demo is above)
  • martinstoeckli
    martinstoeckli almost 10 years
    The workflow looks good to me, what i wondered is how the hash is calculated, or don't you use a hash to store passwords in this keystore? It should be a slow adaptable hash algorithm like BCrypt or PBKDF2 to be secure. Then the salt should ideally be really random, not derrived from other parameters. When i submitted the forgotten-password form, the framework sent an email with a token which is good, this token should not be stored in the database though, only its hash should be stored.
  • OhadR
    OhadR almost 10 years
    actually, Spring does the encoding work - and they use SHA256. in my code, i use the same algorithm to adapt. plus, to be secured - the link is not stored in the DB. the link that is sent to the user is encrypted with assymetric key. makes sense?
  • Sanne
    Sanne almost 10 years
    -1 explain what you did instead of pointing out to an external source.
  • OhadR
    OhadR almost 10 years
    @Sanne: if i write the explanation, will you upvote? :-)
  • Sanne
    Sanne almost 10 years
    @OhadR: If its relevant and better than the other answer yes, but in my opinion answers like these should be removed. Almost nobody has time to go to your source and look everything up. This site is for staying on topic ;) It is highly irritating answers like yours. Paste the part of your code that is relevant here.
  • OhadR
    OhadR almost 10 years
    @Sanne - i can see your point; I do agree with the flow of the accepted answer; I've posted this because developers are forced to implement this, because they cannot find easily an open source that does so. I thought this is the right place to let these developers know about my free open source, which can help them - this is what SO is all about....
  • Sanne
    Sanne almost 10 years
    @OhadR: Yeah I understand. But the whole question doesn't even speak of a certain language. It's really out of place in my eyes. Hence I got irritated when reading your answer, enough to even write this message and now writing my third reply. If you do want to promote your own code, at least give an answer or summary to the question and then state the link. instead of just saying "look here..". This is not an advertisement site.
  • user1069528
    user1069528 over 7 years
    IMO bad idea. The sniffer could do a lot of damage before the real party was able to contact customer support.
  • PeakGen
    PeakGen about 7 years
    My support goes for both options because 1st option is applicable for web apps while the second option is best for mobile only apps.