0

I am implementing ASP.NET Core Identity with IdentityServer4. One feature is password reset, and I found that all the examples (e.g. the IdentityServer4 quick start and the ASP.NET Identity example) tend to do this:

  • The Password Reset Token ("Code") is passed to the page via the URL in the e-mail and "magically" posted along the new password.
  • The form (in addition to of course a new password) requires you to fill out an e-mail address.

This is needed because you need an ApplicationUser when using a password reset token, which you can only get by things like UserId, Name, and Email.

I've seen plenty of sites (some major) only requiring the new password and no e-mail. Given that you can only receive a password reset token through email, it feels kind of silly to ask a user to re-enter their email ("I just clicked on a link in my mailbox, why are you asking for my e-mail address!?").

What is the rationale here? I'm tempted to include the UserId in the reset password URL and also automagically include it in the form for posting a fresh password, but given that all major examples ask for an e-mail address I'm questioning: what would be the security implications of that?

Jeroen
  • 839
  • 9
  • 15

1 Answers1

2

I'm not familiar with this exact framework, so this is generic security advice, but: The correct way to handle password reset flows (with a token contained in a URL that the user is emailed, and then clicks), is for the token itself to be used to look up the user. You don't need any other way to identify the user (the token is unique for every user, and indeed for every password reset attempt, of course).

It is a very bad idea to even have some other way to identify the user who is resetting their password, because if you do that, you open yourself to the risk of an attacker entering somebody else's email address (or user ID, or name, or whatever) and resetting the other person's password instead. To prevent that, you would need to confirm that the token from the link is the current password reset token for the indicated user, and if you can do that, you can identify the user from the token directly and there's no need for the user to supply the identity. Passing the identity in the URL is not any safer; an attacker can modify the URL before loading the web page just as well as they can lie about their identity in a web form.

If there's no way for the server to look up a user from their password reset token, then frankly that is an incredibly silly bug and should be reported and/or patched (if open source) immediately. A bug like that would make me seriously question the quality of the entire authentication codebase.


EDIT

The possibility that the requirement exists to provide additional security occurred to me, but I didn't include it in the answer initially as it seemed unlikely. It should be completely impossible to brute-force the tokens; they should be minimum 128 bits of securely-generated random string, with a lifetime measured in minutes (single-digit hours at most) before use and expiring immediately upon use. That leaves only ways for an attacker to capture the token before it is used, and there are mitigations to all of those vectors:

  • Attacker captured the victim's URLs (perhaps in a proxy log or similar) and manages to use the token to reset the victim's password before the victim can do it themselves. The odds of this ever happening in a situation where the attacker couldn't also determine the victim's email address is pretty minimal (as it implies that the attacker is able to view the plain text of the victim's HTTPS traffic).
  • Victim clicks the link then walks away from their computer before completing the password reset, without locking it, and the attacker sits down in front of the machine. This both involves a level of "user is being incredibly foolish" (and you know what they say about making something idiot-proof), and the attacker could just go look up the victim's email address (they're sitting at the computer where the victim just clicked the link!) in the event that the attacker didn't already know it. This attack is more properly mitigated by making the password reset page itself have only a very short lifetime (it should not take more than five minutes to enter a new password, max, even assuming the user is disabled and must use a really slow input system).

There is an argument for, in extremely paranoid situations, protecting against the first case by accepting the cost of user hassle and taking the risk of insecure implementation. For the most part, it seems like a clear net negative in utility. The second case doesn't even really bear mentioning because the "protection" of requiring the identity is trivially bypassed. Unless there's some other scenario I'm missing, this provides negligible benefit.

CBHacking
  • 40,303
  • 3
  • 74
  • 98
  • IIRC having to provide the e-mail is an _extra_ check. That is, you cannot use a token to reset someone else's password. (Also: ASP.NET Identity and IdentityServer are both quite mature open source products, so I don't much doubt the quality, instead would think either my own interpretation is wrong or the setup is overkill for my purposes.) - Either way: thank you for your answer, very insightful! – Jeroen Jan 21 '19 at 19:55
  • I considered that possibility but initially didn't think it was plausible, seems like security theater (hassling people to seem secure, without providing any non-negligible benefit). I've edited my thoughts on that subject into the answer, though. – CBHacking Jan 21 '19 at 21:03