2
votes

I am designing some Forgot Password functionality in an ASP.NET application, and had a question about the best way to secure the endpoint where a user can reset their password.

How I imagine this to work is (roughly) the following:

  • User clicks 'Forgot Password' on the login form
  • User is taken to a screen where they will enter their email associated with their account
  • User is then taken to a screen where they can answer some security questions (required by my company)
  • After answering questions correctly, the user will be sent an email containing a link.
  • User clicks the link in their email which will take them to a password reset form

My question here is, how can I ensure that when someone arrives at this password reset form that they arrived there from clicking on that email link, and didn't just manually type in the URL to get there?

One solution I've thought of was to encrypt some data and append it as a parameter in the URL inside the email. So when they click that link, I can decrypt the data and ensure it came from a valid email before serving the form. But I'm not sure the best way to go about this.

1
Have you heard about JSON Web Tokens?grooveplex
@grooveplex I have not, this looks like it could be just what I needderuitda
How you are describing it is exactly how we do it at our company, except that we also make the encrypted key expire after 15 minutes as to prevent it from sitting in that person's inbox forever waiting for a hacker to find.sourkrause

1 Answers

2
votes

A solution consists of creating a token that can be used once on the reset page. You send by email a link similar to https://example.com/PasswordLost?token=467dc4ad9acf4, then the site checks that the token is valid and displays the password change page. To add more security it is possible to limit the validity of the token in time: about ten minutes are largely sufficient. Once in use, the token should no longer be usable.

There are many ways to generate the token. You can generate a random string and store it in a database with the associated email address and the expiration date of the token. Then, you can validate it by querying the database. The other solution that I prefer, is to generate a token that is ciphered by the server. Then, you can decipher it and validate the data it contains (user email and expiration date, last password changed date). This way you don't have to store anything on the server. This is what ASP.NET Core Identity does.

You can read my blog post about how to implement Password reset feature in a web application? for more information.