Error de ASP.NET Core: error de token no válido al implementar la contraseña olvidada
En miASP.NET MVC Core 1.1.1
aplicación conIndividual User Accounts
modo enVS2017 ver 15.3.3
Estoy implementandoForgot Password
funcionalidad La aplicación está enviando correctamente el correo electrónico con un enlace generado. Puedo abrir mi correo electrónico y puedo ver el enlace generado de la siguiente manera. El enlace muestra correctamente elResetPassWord.cshtml
ver. Pero cuando ingreso el nombre de usuario requerido, la contraseña, confirmo la información de la contraseña y hago clic en el botón Enviar, obtengo elInvalid Token
error.Pregunta: ¿Cómo resolver el problema?
NOTA:
A. ElPasswordReset
la funcionalidad funciona bien si estoy conectado y quiero restablecer mi contraseña a otra cosa.
B. No estoy seguro de si es relevante o no: no estoy usando el correo electrónico como nombre de usuario. En cambio, he cambiado los atributos de correo electrónico en elAccountCountroller
de
[Required]
[EmailAddress]
public string Email { get; set; }
a
[Required]
public string UserName { get; set; }
etc., etc. y tienen atributos de usuario extendidos enApplicationUser.cs
como sigue:
ApplicationUser.cs
// Add profile data for application users by adding properties to the ApplicationUser class
public class ApplicationUser : IdentityUser
{
public string UserFullName { get; set; }
[Column(TypeName = "varchar(50)")]
public string UserEmaill { get; set; }
[Column(TypeName = "varchar(15)")]
public string UserCity{ get; set; }
}
Cuerpo de mi correo electrónico que envió la aplicación:
Please reset your password by clicking here: <a href='http://localhost/HPF/Account/ResetPassword?userId=1db73091-8098-4427-9a1a-1897dcabea90&code=CfDJ8IgLyyEqB6dPkvwFmW%2BJlPrg%2Fpz%2FiNTD442K1KoBG7MSx3zp6TFSY5w0Xj49cG87P%2BkGSWalD6YbbRlrLP4qAEORuoaHZM%2BMe0G08Y9EeUycbhNxx%2FpEv2z3sJ%2BMr4ZccLBO08iwlbIxBnXkJ5gu%2Bsnoo5FHAKysp85%2FrLdbS47smj%2Bt9kaaFA5DDBkzmR%2Bb0HTV2FL8CyjH2M1wCjLgcSC2Jg6BIcDAVUd7jEwxB8V9upAVh%2FR3FJCk2OAJU4w4Fg%3D%3D'>link</a>
Controlador:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
if (ModelState.IsValid)
{
var user = await _userManager.FindByNameAsync(model.UserName);
string sUserEmail = user.UserEmail; //I Added this. Note the email is not the user name in my app
if (user == null)
{
// Don't reveal that the user does not exist or is not confirmed
return View("ForgotPasswordConfirmation");
}
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
// Send an email with this link
var code = await _userManager.GeneratePasswordResetTokenAsync(user);
var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
await _emailSender.SendEmailAsync(sUserEmail, "Reset Password", $"Please reset your password by clicking here: <a href='{callbackUrl}'>link</a>");
return View("ForgotPasswordConfirmation");
}
// If we got this far, something failed, redisplay form
return View(model);
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ResetPassword(ResetPasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await _userManager.FindByNameAsync(model.UserName);
if (user == null)
{
// Don't reveal that the user does not exist
return RedirectToAction(nameof(AccountController.ResetPasswordConfirmation), "Account");
}
var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password);
if (result.Succeeded)
{
return RedirectToAction(nameof(AccountController.ResetPasswordConfirmation), "Account");
}
AddErrors(result);
return View();
}
ACTUALIZAR
Lo intentécode = System.Net.WebUtility.UrlEncode(code);
despues de la lineavar code = await _userManager.GeneratePasswordResetTokenAsync(user);
dentroForgotPassword(...)
Método POST; pero sigue siendo el mismo error. Entonces también intentévar code = System.Net.WebUtility.UrlDecode(model.Code);
antes de la lineavar result = await _userManager.ResetPasswordAsync(user, code, model.Password);
dentroResetPassword(...)
Método POST; mismo error de nuevo.