24

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...

Ravikumar B
  • 779
  • 1
  • 14
  • 25
Pramod Gehlot
  • 319
  • 2
  • 4
  • 17

5 Answers5

46

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.

Jeroen
  • 60,696
  • 40
  • 206
  • 339
Mansoor
  • 743
  • 11
  • 18
  • 3
    For me, this worked when the UrlEncode/Decode as described in other answers didn't. – Adrian Carr Oct 21 '16 at 15:41
  • i also the same issue i can't getting '==' in the last end from code so how can handle this i am code send via query string in the mail and i m also try this WebUtility.UrlEncode(code) in the mail send and getting time WebUtility.UrDecode(Model.code) using this but still getting issue and end of getting invalid token. – coderwill Apr 10 '17 at 12:18
  • This save me two times – Almeida Jun 07 '17 at 20:30
  • @Mansoor Would you have any suggestion for my [this](https://stackoverflow.com/q/46249048/1232087) post. I tried your above suggestion but it did not work. – nam Sep 16 '17 at 16:43
  • Really curious why Decode didn't work for me either. This answer does work and saved me a lot of headache since the Token isn't always generated with that symbol. – JoeCo Nov 20 '17 at 20:52
34

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.

Tyler Durden
  • 1,506
  • 13
  • 21
  • 1
    This was also my problem. I just updated the nulls with a random string and it seemed happy with that! Lots of swearing and rage diffused. I'm in your debt. – Shawson Jan 25 '17 at 14:53
  • Thanks this solved my problem which appears to be the same due to adding SecurityToken after most of our users, but what about when new users are added? Will they be given a valid security token initially? – Ryan Feb 20 '17 at 23:23
  • 3
    This fixed my issue - just ran `UPDATE [AspNetUsers] SET [SecurityStamp] = NEWID() WHERE [SecurityStamp] IS NULL` to fill in the NULLs then worked fine. – Jammer Sep 18 '17 at 13:42
  • But how do we prevent it from happening again? – barnacle.m Mar 01 '18 at 13:29
  • null SecurityStamp was my issue. Thanks! – Elnoor Apr 06 '18 at 07:55
2

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);
Dipendu Paul
  • 2,685
  • 1
  • 23
  • 20
1

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

Florian K
  • 602
  • 9
  • 30
0

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.

Afshar Mohebi
  • 10,479
  • 17
  • 82
  • 126
  • removed data import for that specific table and instead used UserManager to create users from old database. – Afshar Mohebi Nov 15 '16 at 08:46
  • @TylerJamesHarden I do not remember, maybe I have posted my answer without reading your answer first. BTW sorry for any inconvenience. – Afshar Mohebi Feb 15 '17 at 10:23
  • I had this issue, to create correct valid tokens I put new GUID in the security stamp field for the user. Once I did that it started working – MattjeS Aug 17 '17 at 13:42