Token invalid on reset password with ASP.NET Identity

16k views Asked by At

I've implemented ASP.NET Identity in my MVC application by copying the code from the VS 2013 templates. The basic thing is working, but I couldn't get the Reset Password to work. When I show the "forgot password" page an email is generated which contains the token. This token is returned by the method:

UserManager.GeneratePasswordResetTokenAsync(user.Id)

When I click the link the reset password forms open and lets the user input their email address and a new password. Then the call to the change password functionality is made:

UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);

This looks good to me, but the result is always a "Invalid Token" and I don't get why that is.

Does anybody have an idea why it isn't working? And where the hell is the token stored? I thought it must be in the database somewhere around the AspNetUsers table...

5

There are 5 answers

5
Mansoor On BEST ANSWER

The token generated by UserManager in ASP.NET Identity usually contains "+" characters which when passed as a query string get changed into "" (a space) in the URL. In your ResetPassword ActionResult replace "" with "+" like this:

var code = model.Code.Replace(" ", "+");
//And then change the following line 
UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);
//To this one so it uses the code(spaces replaced with "+") instead of model.Code
UserManager.ResetPasswordAsync(user.Id, code, model.Password);

That should do the trick. I had the same problem and found the answer here.

5
Tyler Durden On

Just wanted to add that the most common issue outside of HTML encoding/decoding is that your user entry in the database may be missing a SecurityStamp. There is a bug in ASP.NET Identity where one function sets it to null when creating the token, whereas another when validating the token checks for an empty string.

If your SecurityStamp is null or an empty string, this will cause the invalid token issue.

0
Dipendu Paul On

For me security stamp was okay. Inline with accepted answer, I used encode method to encode the code attached with reset link using HttpContext.Current.Server.UrlEncode, like so:

string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
string callbackUrl = ConfigurationManager.AppSettings["baseurl"] + "/resetpassword?email=" + user.Email + "&code=" + HttpContext.Current.Server.UrlEncode(code);
1
Florian K On

If your SecurityStamp changes after generating your token the token is also invalid.

So for example you Generate your Token using

UserManager.GeneratePasswordResetTokenAsync(user.Id);

and afterwards call

UserManager.RemovePasswordAsync(user.Id);

Your SecurityStamp gets renewed and so the Token is now invalid

3
Afshar On

In my case this was because data in database were imported from another database incorrectly. SecurityStamp field was null so I got invalid token error.