We have 2 separate ways for people to perform a forgot password: 1. Via the website - mywebsite.com/account/forgotpassword 2. Via our App - Clicking the "Forgot Password" passes the users email address to our asp.net web api which in turn creates the code and sends the email.
Clicking the link in the email brings up the correct page where we can enter the email and new password. When resetting the password using option 1, it works fine. Using option 2 gives an invalid token error. Both the website and web api are on the same server.
Here's the Web api code:
var user = await UserManager.FindByEmailAsync(email);
var code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
var callbackUrl = $"/Account/ResetPassword?userId={user.Id}&code={code}";
var path = System.Web.Hosting.HostingEnvironment.MapPath("~/Content/emails/ResetPassword.html");
var body = GenerateEmailBody(user);
await UserManager.SendEmailAsync(user.Id, "Reset Password", body);
Here's the website code
var user = await UserManager.FindByEmailAsync(model.Email);
if (user == null)// || !(await UserManager.IsEmailConfirmedAsync(user.Id)))
{
// Don't reveal that the user does not exist or is not confirmed
return View("ForgotPasswordConfirmation");
}
// Send an email with this link
string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
var body = GenerateEmailBody(user);
await UserManager.SendEmailAsync(user.Id, "Reset Password", body);
I verified that the UserTokenProvider is the same in both as well.
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("IdentityStuff"));
I read that MachineKey can cause this issue except we're only using a single server.
An additional piece of info that is worth mentioning is when the website was created, it didn't have identity added to it. This was an after thought. The web api started off with identity.