Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Review my design: Password resetting facility for web site

When someone has lost a password, they click on the lost or forgotten password link. They will need to enter their email address, then answer their own secret question if the secret question is correct, an email will be sent to them with a link that expires after 24hrs.

As the email is sent, a record is entered in a database table holding this information: - the email of the person who needs to reset the password - the hour which the resetting of the password will expire - the hour which the request to rest the password was submitted.

The sent link will lead the user to a form that allows them to enter their new password. In this form they will need to enter their email address and their password X2.

When they click on submit, a check is made against db to ensure that the email is valid (one that the password is being reset) and has not yet expired (by comparing the two dates to see if the expiry time has passed, which is 24 hrs)

If the email is valid, and has not yet expired, and the two passwords match & meet the minimum req, then the new password is applied.

A confirmation message is given on success.

Q1. Is this a good model for password recovery? Q2. How can I make sure that the link that is sent to the user's address is unique? In that no one will get the same link? So that nobody could just go to the password reset page and try different emails, rather have each account that needs to be reset have their own unique URL that work for that account only.

Regarding Q2:

I was thinking that when the user requests to have their password reset, a random unique id is generated and stored in the same record that expires after 24hrs. This random unique id's column could be called "rid"

The link in the email that will be sent to the user will end with ?rid=xxxxxxxxxxxxx

When the user clicks on submit in the page that resets the password, the "rid" at the top of the page is used to get the corresponding email address from the db, to compare it with the email address in the form. Doing this can ensure that each password reset case will have its own unique URL that no other account can use to reset its password.

Is this a viable solution?

Any contributions or suggestions will be appreciated.

like image 463
Nich Avatar asked Jul 11 '10 03:07

Nich


People also ask

Why do websites ask you to reset your password when you forget it and not give Youyour password directly from their database?

This explains why "Forgot Password" links behave as they do. Websites can't just email you your password because they don't know what it is! Instead, they reset your password with a temporary one or ask you to set a new one so that they can update the record they have for you.

How do I reset my authentication password?

Reset your password using a code from your authenticator appSelect Enter a code from my authenticator app, and then select Send Notification. Open your authenticator app, type the verification code for your account into the box, and then select Next. Type and confirm your new password, and then select Finish.


1 Answers

Optimally:

  1. Log me in through OpenID. Less coding complexity, less clicking, less typing, less time wasted.
  2. Done. Question is moot. No need to worry any more, someone else already solved this problem.

There are a billion sites implementing a billion authentication schemes and in 99.999% of the cases it's unnecessary. Why should I as a user trust you as a developer to not store my password in plain-text or leak it or get hacked yourself? Few people use different passwords for every site...

If that's not possible, then make is as hassle-free as possible:

  1. I click a "forgot password?" link. This automatically sends a mail if I've entered an e-mail already (e.g. after a failed log-in attempt). If I haven't entered one, simply hide the password field and tell me to do so. Don't reload or forward me to a different page.
  2. I get a link to with some key (for example https://site.com/account/reset?key=a890ea8219175f890b7c123ee74a22). Some unique hash that is tied to my account and expires in so and so many hours. Use SSL if at all possible.
  3. I click the link and you fetch my account details by the key, making sure it is valid and hasn't expired. I type in my new password twice. I already know what my e-mail address is, and you already know what my e-mail address is, and any would-be hacker would also know what my e-mail was, so don't ask me to type it in. Having the link last a whole day is overkill. Time it out in an hour or less.
  4. I hate the security question. Don't ask me that. It's basically just a second password that's deliberately made less secure so you'll always remember it. I don't have frequent flier miles, I don't know my mother's maiden name, etc. Stop it. I know it's there to keep out strangers who might have hacked your e-mail, but unless you're PayPal I think it's just over-engineering.
  5. When you have confirmed that the passwords match and they are acceptable, update the database (store only a salted hash of my password, not the password itself!) and log me in immediately. Do not redirect me to the log-in page where I have to retype information I've already given you several times now (and even though you already know it's me and trust me enough to change my own password). That is so annoying. Users are impatient.

I also dislike randomly generated passwords based on the following:

  1. Usually I just copy-paste the password from the mail anyway. Copy-pasting a password is something you never want the user to do.
  2. I have to go change the password manually, which means messing around in the user control panel or account settings or whatever. I am getting impatient! You could pup up with a "change your password" the minute I log in with a one-time password, but this means added code complexity. You now need to add a flag for this, add another redirect, handle the case where a user times out on entering a new password, etc.
  3. Because I am only human, and humans have ADHD, I usually forget to do the above and I end up with a crap password I have to find and copy from my e-mail the next time I need to log in as well. My fault, but I'll still blame your site for it. ;-)

The randomly generated password solution is also implying the mentality that you'll always use a password-based solution, when link-based authentication seems to be the future (OpenID, etc.) in usability and security (I don't want a hundred small sites to know my login-details!).

Update to respond to comment:

Why the hash should be enough: if a hacker can guess the full 128+ bits (say) of your generated hash (and within an hour), then why wouldn't he or she also be able to guess the e-mail? I know that it "feels" a lot more secure to ask for the e-mail and/or a security question as well, but if you think about it, e-mails are usually very predictable and uniform, with low entropy rate. I doubt they can be counted on as containing more than 50 bits of information. (Probably a lot less.) I bet you I'd sooner guess your e-mail than I would a 50-bit random integer. But if it is a real worry, all you need to do is add more bits to the hash. 256 bits or so ought to do it for overkill mode -- SHA256(salt, email, old pw hash, time stamp, maybe some bytes from /dev/urandom) or similar... If a hacker can predict that, there's not much you can do really. Obviously he has control of The Matrix and could just project his mind onto the magnetic platters inside your hard drives if he wanted to.

Still Pro-OpenID: any new site I visit that demand I create a user ought to be very convincing as to why they want to know my (throwaway) password and what they offer me in security that OpenID or Google/Facebook/etc. does not -- or why they don't trust Google/Facebook/etc. Nobody (that I know) goes around remembering 30 different passwords. Usually people reuse them, so if these third party site creators wanted to, it'd be really easy for them to scam their users. If I registered at your site with my usual info, you could immediately take over my Last.FM and Reddit accounts if you wanted to, as well as probably a dozen sites I've used a couple of times and forgotten about. In fact, in these modern times, I kinda expect sites to either be ignorant or have malicious intent if they want details they strictly do not need, so that's why I call it a throwaway password -- with every sign-up it feels like I am saying "here, have my Reddit account, it's the same L/P as I'll be using for your site (otherwise I'd just forget). It's fine, I'm not particularly attached to it any way." Of course, Google could actually take over everything of my online self if they wanted to, but for now I'll trust Google more than you (no offense!).

like image 110
integer Avatar answered Oct 13 '22 08:10

integer