Kriya and Meditation for Software / IT Professionals. Conducted by Bipin Joshi in Thane. Read more...
Learn ASP.NET MVC, ASP.NET Core and ASP.NET Design Patterns. Courses conducted by Bipin Joshi on weekends. Click here for more details.

ASP.NET Core Identity - Allow Password Reset

In the previous two article (Part 1 and Part 2) you learnt to implement the ASP.NET Core identity in your web applications and also to add email verification support. In this article you will learn to enable password reset so that users can reset their passwords and specify a new password.

The password reset step in ASP.NET Core Identity works as follows:

  • A user indicates that he wants to reset his password. He does so by specifying his UserName.
  • The system then generates a password reset token (just like the email verification token you used in the previous part)
  • The system sends an email to the user along with a link to reset the password. This link contains the password reset token.
  • The user clicks on the password reset link and is presented with a form wherein new password can be supplied.
  • The system resets the password after validating the token and then assigns the new password to the user.

To implement password reset, you need to add a view model class and a couple of views. Let's begin.

Open the Login view and modify it to include another form for resetting the password. The following markup shows the new form.

<h1>Reset Your Password</h1>

<form asp-controller="Account" 
       asp-action="SendPasswordResetLink" 
       method="post">

    <table>
        <tr>
            <td><label asp-for="UserName">User Name :
            </label></td>
            <td><input name="UserName" type="text" /></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" 
                       value="Reset Password" />
            </td>
        </tr>
    </table>
    <strong>@ViewBag.Message</strong>
    <div asp-validation-summary="All"></div>

</form>

Notice that the above form contains textbox for entering user name and submits to the SendPasswordResetLink() action. The following figure shows how the above form looks like in the browser:

The SendPasswordResetLink() action is shown below:

public IActionResult SendPasswordResetLink(string username)
{
    MyIdentityUser user = userManager.
         FindByNameAsync(username).Result;

    if (user == null || !(userManager.
          IsEmailConfirmedAsync(user).Result))
    {
        ViewBag.Message = "Error while 
                resetting your password!";
        return View("Error");
    }

    var token = userManager.
          GeneratePasswordResetTokenAsync(user).Result;

    var resetLink = Url.Action("ResetPassword", 
                    "Account", new { token = token }, 
                     protocol: HttpContext.Request.Scheme);

    // code to email the above link
    // see the earlier article

    ViewBag.Message = "Password reset link has 
              been sent to your email address!";
    return View("Login");

}

The SendPasswordResetLink() action receives the username as entered by the user on the Login view. It then generates a password reset token using GeneratePasswordResetTokenAsync() method of the UserManager. The GeneratePasswordResetTokenAsync() method accepts a MyIdentityUser object whose password is to be reset.

Then a URL is generated containing the password reset token in the query string. The URL points to the ResetPassword() action (discussed next). Note that the code that actually sends an email has been omitted for the sake of clarity. A sample URL looks like this:

http://localhost:49310/Account/ResetPassword?token=....

Before you develop the ResetPassword() actions and the ResetPassword view, add new view model class - ResetPasswordViewModel - in the Models folder. This class is shown below:

public class ResetPasswordViewModel
{
    [Required]
    public string UserName { get; set; }
    [Required]
    [DataType(DataType.Password)]
    public string Password { get; set; }
    [Required]
    [DataType(DataType.Password)]
    public string ConfirmPassword { get; set; }
    [Required]
    public string Token { get; set; }
}

The ResetPasswordViewModel contains four properties - UserName, Password, ConfirmPassword and Token. The Token property holds the password rest token generated earlier.

The ResetPassword() GET action displays ResetPassword view for supplying the new password.

public IActionResult ResetPassword(string token)
{
    return View();
}

The markup of ResetPassword view is as follows:

@model ResetPasswordViewModel

...
...

<h1>Reset Your Password</h1>

<form asp-controller="Account" 
      asp-action="ResetPassword" 
      method="post">

    <input type="hidden" asp-for="Token" />
    <table>
        <tr>
            <td><label asp-for="UserName"></label></td>
            <td><input asp-for="UserName" /></td>
        </tr>
        <tr>
            <td><label asp-for="Password">
New Password</label></td>
            <td><input asp-for="Password" /></td>
        </tr>
        <tr>
            <td><label asp-for="ConfirmPassword">
Confirm New Password</label></td>
            <td><input asp-for="ConfirmPassword" /></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" 
value="Reset Password" />
            </td>
        </tr>
    </table>

    <div asp-validation-summary="All"></div>

</form>

A sample run of the PasswordReset view looks like this:

The ResetPassword view POSTs to ResetPassword() POST action. This action is shown below:

[HttpPost]
public IActionResult ResetPassword
                (ResetPasswordViewModel obj)
{
    MyIdentityUser user = userManager.
                 FindByNameAsync(obj.UserName).Result;

    IdentityResult result = userManager.ResetPasswordAsync
              (user, obj.Token,obj.Password).Result;
    if (result.Succeeded)
    {
        ViewBag.Message = "Password reset successful!";
        return View("Success");
    }
    else
    {
        ViewBag.Message = "Error while resetting the password!";
        return View("Error");
    }
}

The ResetPassword() POST action receives ResetPasswordViewModel object containing user name, new password and the password reset token. It then calls ResetPasswordAsync() method of UserManager in an attempt to reset the user's password to the new value. If all goes well the IdentityResult will be Succeeded. Accordingly a success message or an error message is displayed to the user.

That's it for now! Keep coding!!


Bipin Joshi is a software consultant, an author and a yoga mentor having 22+ years of experience in software development. He also conducts online courses in ASP.NET MVC / Core and Design Patterns. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Meditation and Mindfulness to interested individuals. To know more about him click here.

Get connected : Twitter  Facebook  Google+  LinkedIn

Posted On : 12 September 2016


Tags : ASP.NET ASP.NET Core MVC C#