Invalid Token on password reset Asp.net Core Identity

Prathamesh Shende 441 Reputation points
2022-07-20T18:26:55.773+00:00

I checked the token is identical
but still showing error Invalid Token and password is not changes on Reset.
here is the code

[HttpGet]  
public IActionResult ForgotPassword()  
{  
    ViewBag.ShowModelError = "collapse";  
    return View();  
}  
[HttpPost]  
public async Task<IActionResult> ForgotPassword(EmailViewModel input)  
{  
    ViewBag.ShowModelError = "collapse";  
    if (!ModelState.IsValid)  
    {  
        return View();  
    }  

    var user = await _userManager.FindByEmailAsync(input.Email);  
    if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))  
    {  
        // Don't reveal that the user does not exist or is not confirmed  
        return RedirectToAction(nameof(ForgotPasswordConfirmation));  
    }  

    // For more information on how to enable account confirmation and password reset please  
    // visit https://go.microsoft.com/fwlink/?LinkID=532713  
    var code = await _userManager.GeneratePasswordResetTokenAsync(user);  
    code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));  

    var callbackUrl = $"{Request.Scheme}://{this.Request.Host}/Account/ResetPassword?code={code}&userid={user.Id}";  

    //Console.WriteLine(HtmlEncoder.Default.Encode(callbackUrl));  
     sendService.SendMail(input.Email, "Reset Password | Innovus", $"Please reset your password by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");  

    return RedirectToAction(nameof(ForgotPasswordConfirmation));  
}  
[HttpGet]  
public IActionResult ResetPassword(string code = null, string userid = null)  
{  
    if (code == null || userid == null)  
    {  
        return BadRequest("A code must be supplied for password reset.");  
    }  
    else  
    {  
        var user = _userManager.FindByIdAsync(userid);  
        if (user == null)  
        {  
            return BadRequest("A code must be supplied for password reset.");  
        }  

        var resetPassword = new ResetPasswordViewModel  
        {  
            Code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code)),  
            Email = user.Result.Email,  
        };  
        return View(resetPassword);  
    }  
    //ViewBag.ShowModelError = "collapse";  
    //return View();  
}  
[HttpPost]  
public async Task<IActionResult> ResetPassword(ResetPasswordViewModel input)  
{  
    if (!ModelState.IsValid)  
    {  
        return View();  
    }  

    var user = await _userManager.FindByEmailAsync(input.Email);  
    if (user == null)  
    {  
        // Don't reveal that the user does not exist  
        return RedirectToAction(nameof(ResetPasswordConfirmation));  
    }  

    var result = await _userManager.ResetPasswordAsync(user, input.Code, input.Password);  
    if (result.Succeeded)  
    {  
        return RedirectToAction(nameof(ResetPasswordConfirmation));  
    }  

    foreach (var error in result.Errors)  
    {  
        ModelState.AddModelError(string.Empty, error.Description);  
    }  
    return View(input);  
}
Developer technologies ASP.NET ASP.NET Core
{count} votes

2 answers

Sort by: Most helpful
  1. Prathamesh Shende 441 Reputation points
    2022-07-21T07:41:40.49+00:00

    I checked with link it accept the user.ID in string return. this was working in asp.net core 2.2
    I am using asp.net core 6.

    The problem find out when link converts on Get Method of ResetPassword - It decode properly and on Post Method It will get change back to encoded format. I don't know ? and I also pass it into model for view.

    So the fix is, I Decode it on Post Method So It's working for me .

    [HttpPost]
    public async Task<IActionResult> ResetPassword(ResetPasswordViewModel input)
    {
    if (!ModelState.IsValid)
    {
    return View();
    }
    var user = await _userManager.FindByEmailAsync(input.Email);
    if (user == null)
    {
    // Don't reveal that the user does not exist
    return RedirectToAction(nameof(ResetPasswordConfirmation));
    }
    var result = await _userManager.ResetPasswordAsync(user, Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(input.Code)), input.Password);
    if (result.Succeeded)
    {
    return RedirectToAction(nameof(ResetPasswordConfirmation));
    }
    foreach (var error in result.Errors)
    {
    ModelState.AddModelError(string.Empty, error.Description);
    }
    return View(input);
    }

    0 comments No comments

  2. Nitin Tarkar 0 Reputation points
    2023-08-08T10:20:12.1933333+00:00

    I faced same issue if I click on reset link that I got in email after 10 mins. The DataProtectionTokenProviderOptions --> TokenLifespan was set to 10 mins.

    I changed DataProtectionTokenProviderOptions --> TokenLifespan to 2 hrs.

    Now if I click on link I got in email within 2hrs then it worked. If I click on link after 2hrs then I am getting Invalid Token issue.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.