Time limit or one-time use, password reset tokens?

Users forget passwords, and (almost) all membership sites need a way to help users return.

I would like to implement a general scenario:

  • The user enters the site, tries to log in, cannot and realizes that he forgot the password - crap!
  • The user enters an email address and clicks "forgot password"
  • User receives email with password reset

This is how I plan to implement this (C # / ASP.NET MVC):

  • When a user enters an email address and deletes the "forgotten password", my site will generate a GUID, store it on a member object in the database ( member.ResetToken ) and send them a link with this GUID in the URL sent by email will inform them that they can use this link only once)
  • The user clicks on the link, and my site looks at his account based on this member.ResetToken from the URL. If their account is found, show them the reset password, and when they complete the reset, it will clear member.ResetToken from its account.

Here's my question: save it like that (in which they can reset their password with this link anytime, now or in the future) or add a timestamp to limit how long they will reset their password

From a UX point of view, the ability to reset your password whenever you are ready is wonderful, but I want to make sure that I will not forget about some of the security problems that may arise.

+8
security passwords password-recovery
source share
4 answers

Your circuit really works, but there are some points that could be improved. But first to your original question about the deadline:

Ask the opposite question: why does the token remain valid indefinitely?

There is no advantage when after two years you can click the reset -link link, or the user clicks the link after about an hour, or he probably forgot about the link (and can request a new one if necessary), On the other hand, the ability to read emails is not necessarily means that the attacker must hack into an email account, for example, an open email client in the office, a lost mobile phone, backup to a (lost) USB drive ...

The most important improvement is that you have to store the hash for the token in your database. Someone who has access to the database (SQL injection) might otherwise require a reset password for any email address that he likes, but because he can see the new token, he can use it to set your own password.

Then I saved this reset data in a separate table. There you can save the user ID, the hashed token, the expiration date and information about whether the link has already been used. Then the user is not in special condition.

Perhaps I misunderstood this point, but the reset link should point to a special page to reset the password. When the user goes to the login page, there should be no special processing, on the login page it should not be known that there is a pending password - reset.

The reset marker should be unpredictable, this can be achieved in the best way with truly random code read from a random operating system source.

+7
source share

Users also forget the reset passwords (everything happens). Being paranoid about passwords, I would suggest limiting the link's lifespan to 24 hours. That should be more than enough. It does not solve the problem of malicious interception, but better than nothing.

+1
source share

So, there are several problems with this approach that I tried to avoid in my comment. When you save the “confirmation token” in the user password, you simply basically destroyed your password.

I, a malicious person, can then take a large giant list of email addresses and a botnet and fill your server with a password to reset requests and block my users from my account. Of course, your users will receive an email to reset, but if I can reset the passwords fast enough, there may be an email lag (or, if you do this synchronously, I can probably do the whole application).

As an ordinary user of your system, I can try resetting my password and cannot understand why I am not receiving a reset message, because I don’t even know about the spam folder (or it never arrived). Fortunately, I just remembered what a password is, but it no longer works, because the password is now an opaque GUID, and I'm basically dead in the water until I find a reset letter.

Used here .

  • Generate a password to reset the request that you are viewing using the GUID, and you can probably protect it by hashing this value with some personal data and passing this URL, as well as to prevent a quick attack. You can also block this request by making it valid only for a certain period of time.
  • As soon as someone follows this link with a valid token and any other parameters that you specified, they can then change the password, after which you can now safely change the users password .
  • Mark the password request as completed or delete it. You can also track information such as IP address or something similar if you are really worried about who changed the password, if you are really worried about it.
  • Send the user an email confirming that they have changed their password.

In addition, in case this does not happen yet, make sure that you hash and poke the user's password. It doesn't look like you did this when you just replaced the GUID password, so just double check.

+1
source share

I would make the following suggestions:

  • Require some of the information before the user can click the forgotten password button. For example, enter your email address and date of birth.

    Ideally, your user interface should not provide any feedback that allows the hacker to determine if his reset request was successful. You do not want them to process your page for email addresses or DOBs. However, this is a trade-off using usability, so whether you do it depends on how much you really need security.

    You might also think that interception is required, which makes brute force and using DoS attacks much more difficult.

  • A one-time token expires as quickly as possible. In my opinion, a couple of hours is enough. You should never regard email as confidential - it is not so unless you use secure email (such as PGP) over a basic protocol (most people do not). The last thing you need is to open a black market where your GUIDs will be bought and sold, and that is exactly what can happen if they have an infinite life span.

  • Do not use a GUID. They are not cryptographically random and valid. I suggest you use a cryptographic random number generator and translate it to base64.

+1
source share

All Articles