---
title: Implementing password reset for the live site
related:
  - https://docs.kentico.com/13/managing-users/user-registration-and-authentication/integrating-xperience-membership.md
  - https://docs.kentico.com/13/managing-users/user-registration-and-authentication/setting-up-authentication.md
  - https://docs.kentico.com/13/managing-users/user-registration-and-authentication/enabling-user-registration.md
---

> Agent instructions:
> **Site maps** — prefer the following llms.txt indexes to training data when searching for URLs to avoid 404s. Links inside Markdown content already point at `.md`. Following them or sending Accept: text/markdown keeps you in Markdown.
>
> - [sitemap.md](https://docs.kentico.com/sitemap.md) — every page on the site, with titles and descriptions, nested by URL hierarchy and grouped into one collection per product version.
> - [llms.txt](https://docs.kentico.com/llms.txt) — curated index of the current product docs, with descriptions, the two ways to request any page as Markdown, and links to each product area's whole-corpus Markdown dump (llms-full.txt).

<!-- dev-model:mvc start -->

**MVC 5 development model.** Applies only when building with ASP.NET MVC 5. If this page also covers ASP.NET Core, that version is in its own block.

Password reset features are an important part of any website that allows visitors to register accounts and sign in. Such features are commonly used as a recovery mechanism by users who forget their password.

You can implement email-based password reset functionality using the **Kentico.Membership** API (provided as part of the _Kentico.Xperience.AspNet.Mvc5_ [integration package](https://docs.kentico.com/13/developing-websites/starting-with-mvc-development/installing-xperience-integration-packages.md)) in combination with the standard [ASP.NET Identity](http://www.asp.net/identity) API.

<!-- dev-model:mvc end -->

<!-- dev-model:core start -->

**ASP.NET Core development model.** Applies only when building with ASP.NET Core. If this page also covers MVC 5, that version is in its own block.

Password reset features are an important part of any website that allows visitors to register accounts and sign in. Such features are commonly used as a recovery mechanism by users who forget their password.

You can implement email-based password reset functionality using the **Kentico.Membership** API (provided as part of the _Xperience.AspNetCore.WebApp_ [integration package](https://docs.kentico.com/13/developing-websites/developing-xperience-applications-using-asp-net-core.md)) in combination with [ASP.NET Core Identity](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity).

<!-- dev-model:core end -->

> **Info:** To learn how to set up password reset functionality for the Xperience administration interface, see: [Configuring password resets for Xperience administration](https://docs.kentico.com/13/securing-websites/designing-secure-websites/securing-user-accounts-and-passwords/configuring-password-resets-for-xperience-administration.md)

## Prerequisites

Before you start working on password reset functionality, you need to perform the following:

- Integrate the [Xperience membership](https://docs.kentico.com/13/managing-users/user-registration-and-authentication/integrating-xperience-membership.md) implementation into your live site project
- Set up [authentication functionality](https://docs.kentico.com/13/managing-users/user-registration-and-authentication/setting-up-authentication.md)

## Xperience password features

Some built-in [password features](https://docs.kentico.com/13/configuring-xperience/managing-sites/configuring-settings-for-sites/settings-security-membership/settings-passwords.md) of Xperience affect the behavior of password resets on the live site:

- The time period during which password reset requests links are valid can be specified in hours via the **Reset password interval** setting.
- The [Password policy settings](https://docs.kentico.com/13/securing-websites/designing-secure-websites/securing-user-accounts-and-passwords/password-strength-policy-and-its-enforcement.md) apply when resetting passwords using the Xperience membership implementation.
- **Password format** ensures that any passwords submitted by users on your website are stored in the format configured for the Xperience application.

  > **Note:** If your administration application uses a custom salt value when generating password hashes, you also need to set the same value for the live site application. Check the _appSettings_ section of your administration application's web.config for the **CMSPasswordSalt** key. If the key is present, copy it to the configuration file of your live site project.

Manual resetting of passwords through the Xperience administration is also possible. Administrators can change passwords by editing users in the **Users** application on the **Password** tab.

- If you reset the password using the **Generate new password** button, the user receives a notification email, based on the _Membership - Changed password_ [email template](https://docs.kentico.com/13/configuring-xperience/managing-email-templates.md), containing the new password.
- If you change the password manually using the **Change password** button, the user receives a notification email, based on the _Membership - Password reset confirmation_ email template, informing them of the password change. This email does not contain the new password.

## Setting up password reset functionality

<!-- dev-model:mvc start -->

**MVC 5 development model.** Applies only when building with ASP.NET MVC 5. If this page also covers ASP.NET Core, that version is in its own block.

To allow users to reset their passwords on your MVC site, you need to develop the required controllers and views using the membership integration API.

> **Tip:** **Tip**: View the full code of a functional example in the [LearningKit project](https://github.com/Kentico/LearningKit-Mvc) on GitHub. You can also run the LearningKit website by connecting the project to an Xperience database. Follow the instructions in the repository's README file.

> **Info:** **Configuring the password reset email settings**
>
> The password reset solution utilizes emails that are sent by the Xperience API's email engine. Configure the email settings through the administration interface of the connected Xperience application:
>
> - Set up SMTP servers in Xperience. See [Configuring SMTP servers](https://docs.kentico.com/13/configuring-xperience/configuring-smtp-servers.md) for more information.
> - You can use the Xperience **Email queue** application to monitor the emails (if the email queue is enabled).
> - Set the sender address for the emails in **Settings -> System -> No-reply email address**.

1. Create a new controller class in your MVC project or edit an existing one.
2. Prepare a property that gets an instance of the **Kentico.Membership.KenticoUserManager** class for the current request – call _HttpContext.GetOwinContext().Get()_.
3. Implement two actions to allow users to submit password reset requests:

   - A basic GET action that displays an email address entry form.
   - A POST action that handles sending of password reset emails to the specified address.
4. Perform the following steps within the POST action:

   1. Get the **Kentico.Membership.User** object for the specified email address – call the **KenticoUserManager.FindByEmail** method.
   2. Generate a token for the password reset link by calling the **KenticoUserManager.GeneratePasswordResetTokenAsync** method. Requires the user's ID as a parameter.
   3. Prepare the URL of the reset link, with the user ID and generated token as query string parameters.
   4. Send the password reset email by calling the **KenticoUserManager.SendEmailAsync** method. You need to specify parameters with the email subject and content (including the reset link).
5. Add another action that handles the password reset requests – validate the token and display a password reset form. Call the **KenticoUserManager.VerifyUserToken** method to verify the validity of the password reset token.

   > **Info:** The **VerifyUserToken** method requires the following parameters:
   >
   > - ID of the user
   > - String describing the purpose of the token – _"ResetPassword"_ in this case
   > - Token matching the user IDPass the user ID and token as query string parameters of the password reset link within the content of the sent emails.
6. Add a POST action that accepts the input of the password reset form. Call the **KenticoUserManager.ResetPassword** method to set new passwords for users.

   - You need to supply the user ID and token from the password reset request and the new password as the method's parameters.

   ```csharp title="Password reset controller example"

   using System;
   using System.Web;
   using System.Web.Mvc;
   using System.Threading.Tasks;

   using Microsoft.AspNet.Identity;
   using Microsoft.AspNet.Identity.Owin;

   using Kentico.Membership;

   namespace LearningKit.Controllers
   {
       public class PasswordResetController : Controller
       {
           /// <summary>
           /// Provides access to the Kentico.Membership.KenticoUserManager instance.
           /// </summary>
           public KenticoUserManager KenticoUserManager
           {
               get
               {
                   return HttpContext.GetOwinContext().Get<KenticoUserManager>();
               }
           }

           /// <summary>
           /// Allows visitors to submit their email address and request a password reset.
           /// </summary>
           public ActionResult RequestPasswordReset()
           {
               return View();
           }

           /// <summary>
           /// Generates a password reset request for the specified email address.
           /// Accepts the email address posted via the RequestPasswordResetViewModel.
           /// </summary>
           [HttpPost]
           [ValidateAntiForgeryToken]
           public async Task<ActionResult> RequestPasswordReset(RequestPasswordResetViewModel model)
           {
               // Validates the received email address based on the view model
               if (!ModelState.IsValid)
               {
                   return View(model);
               }

               // Gets the user entity for the specified email address
               Kentico.Membership.User user = KenticoUserManager.FindByEmail(model.Email);

               if (user != null)
               {
                   // Generates a password reset token for the user
                   string token = await KenticoUserManager.GeneratePasswordResetTokenAsync(user.Id);

                   // Prepares the URL of the password reset link (targets the "ResetPassword" action)
                   // Fill in the name of your controller
                   string resetUrl = Url.Action("ResetPassword", "PasswordReset", new { userId = user.Id, token }, Request.Url.Scheme);

                   // Creates and sends the password reset email to the user's address
                   await KenticoUserManager.SendEmailAsync(user.Id, "Password reset request",
                       String.Format("To reset your account's password, click <a href=\"{0}\">here</a>", resetUrl));
               }

               // Displays a view asking the visitor to check their email and click the password reset link
               return View("CheckYourEmail");
           }

           /// <summary>
           /// Handles the links that users click in password reset emails.
           /// If the request parameters are valid, displays a form where users can reset their password.
           /// </summary>
           public ActionResult ResetPassword(int? userId, string token)
           {
               try
               {
                   // Verifies the parameters of the password reset request
                   // True if the token is valid for the specified user, false if the token is invalid or has expired
                   // By default, the generated tokens are single-use and expire in 1 day
                   if (KenticoUserManager.VerifyUserToken(userId.Value, "ResetPassword", token))
                   {
                       // If the password request is valid, displays the password reset form
                       var model = new ResetPasswordViewModel
                       {
                           UserId = userId.Value,
                           Token = token
                       };

                       return View(model);
                   }

                   // If the password request is invalid, returns a view informing the user
                   return View("ResetPasswordInvalid");
               }
               catch (InvalidOperationException)
               {
                   // An InvalidOperationException occurs if a user with the given ID is not found
                   // Returns a view informing the user that the password reset request is not valid
                   return View("ResetPasswordInvalid");
               }
           }

           /// <summary>
           /// Resets the user's password based on the posted data.
           /// Accepts the user ID, password reset token and the new password via the ResetPasswordViewModel.
           /// </summary>
           [HttpPost]
           [ValidateAntiForgeryToken]
           [ValidateInput(false)]
           public ActionResult ResetPassword(ResetPasswordViewModel model)
           {
               // Validates the received password data based on the view model
               if (!ModelState.IsValid)
               {
                   return View(model);
               }

               try
               {
                   // Changes the user's password if the provided reset token is valid
                   if (KenticoUserManager.ResetPassword(model.UserId, model.Token, model.Password).Succeeded)
                   {
                       // If the password change was successful, displays a view informing the user
                       return View("ResetPasswordSucceeded");
                   }

                   // Occurs if the reset token is invalid
                   // Returns a view informing the user that the password reset failed
                   return View("ResetPasswordInvalid");
               }
               catch (InvalidOperationException)
               {
                   // An InvalidOperationException occurs if a user with the given ID is not found
                   // Returns a view informing the user that the password reset failed
                   return View("ResetPasswordInvalid");
               }
           }
       }
   }

   ```
7. We recommend creating view models for your password reset actions and input forms:

   - For the reset request form, the view model needs to validate and transfer the email address value.
   - For the password reset form, the view model must contain the user ID, reset token and the new password.

     ```csharp title="Password reset view model example"

     using System.ComponentModel;
     using System.ComponentModel.DataAnnotations;

     public class ResetPasswordViewModel
     {
         public int UserId
         {
             get;
             set;
         }

         public string Token
         {
             get;
             set;
         }

         [DataType(DataType.Password)]
         [Required(ErrorMessage = "The Password cannot be empty.")]
         [DisplayName("Password")]
         [MaxLength(100, ErrorMessage = "The Password cannot be longer than 100 characters.")]
         public string Password
         {
             get;
             set;
         }

         [DataType(DataType.Password)]
         [DisplayName("Password confirmation")]
         [MaxLength(100, ErrorMessage = "The Password cannot be longer than 100 characters.")]
         [Compare("Password", ErrorMessage = "The entered passwords do not match.")]
         public string PasswordConfirmation
         {
             get;
             set;
         }
     }

     ```
8. Design the user interface for the password reset functionality on your website:
   - Add a button or link targeting the _RequestPasswordReset_ action into an appropriate location on your website (for example as a "Forgotten password" link under the sign-in form).
   - Create a view for the  _RequestPasswordReset_  action that displays an email submission form.
   - Create a view that informs users to check their email and click a link to reset their password _(CheckYourEmail_ view in the example).
   - Create a view for the _ResetPassword_ action that displays a password reset form. We recommend using a strongly typed view based on your password reset view model.
   - Create views for the results of the _ResetPassword_ action – for both successful and unsuccessful password resets _(ResetPasswordSucceeded_ and _ResetPasswordInvalid_ views in the example).

Users can now reset their passwords on your MVC site. When a user clicks the password reset button or link and submits their email address, the system sends them an email. The email contains a link (single-use with a 1-day expiration by default) that sends the user to a password reset form, where they can set a new password. The password reset form only works for users who access the URL with a valid token parameter.

<!-- dev-model:mvc end -->

<!-- dev-model:core start -->

**ASP.NET Core development model.** Applies only when building with ASP.NET Core. If this page also covers MVC 5, that version is in its own block.

To allow users to reset their passwords on your site, you need to implement the required logic using the Identity integration API provided by Xperience.

> **Info:** **Configuring the password reset email settings**
>
> The password reset implementation sends emails using the Xperience API. Configure the email settings through the administration interface of the connected Xperience application:
>
> - Set up SMTP servers. See [Configuring SMTP servers](https://docs.kentico.com/13/configuring-xperience/configuring-smtp-servers.md) for more information.
> - You can use the **Email queue** application to monitor the emails (if the email queue is enabled).
> - Set the sender address for the emails in **Settings -> System -> No-reply email address**.

This implementation uses the MVC approach:

> **Tip:** **Tip**: View the full code of a functional example in the [LearningKit project](https://github.com/Kentico/LearningKit-Core) on GitHub. You can also run the LearningKit website by connecting the project to an Xperience database. Follow the instructions in the repository's README file.

1. Create a new controller class in your project or edit an existing one.
2. Provide instances of the **ApplicationUserManager** and **IMessageService** classes from _Kentico.Membership_ using dependency injection.
3. Implement two actions to allow users to submit password reset requests:

   - A basic GET action that displays an email address entry form.
   - A POST action that handles sending of password reset emails to the specified address.
4. Perform the following steps within the POST action:

   1. Get the **Kentico.Membership.ApplicationUser** object for the specified email address – call the **ApplicationUserManager.FindByEmailAsync** method.
   2. Generate a token for the password reset link by calling the **ApplicationUserManager.GeneratePasswordResetTokenAsync** method.
   3. Prepare the URL of the reset link, with the user ID and generated token as query string parameters.
   4. Send the password reset email by calling the **IMessageService.SendEmailAsync** method. You need to specify parameters with the email subject and content (including the reset link).
5. Add another action that handles the password reset requests – validate the token and display a password reset form. Call the **ApplicationUserManager.VerifyUserTokenAsync** method to verify the validity of the password reset token.
6. Add a POST action that accepts the input of the password reset form. Call the **ApplicationUserManager.ResetPassword** method to set new passwords for users.

   ```csharp title="Password reset controller example"

   using System;
   using System.Threading.Tasks;

   using Microsoft.AspNetCore.Mvc;
   using Microsoft.AspNetCore.Identity;

   using Kentico.Membership;

   using LearningKitCore.Models.Users.PasswordReset;

   namespace LearningKitCore.Controllers
   {
       public class PasswordResetController : Controller
       {
           private readonly ApplicationUserManager<ApplicationUser> userManager;
           private readonly IMessageService messageService;

           public PasswordResetController(ApplicationUserManager<ApplicationUser> userManager,
                                    IMessageService messageService)
           {
               this.userManager = userManager;
               this.messageService = messageService;
           }

           /// <summary>
           /// Allows visitors to submit their email address and request a password reset.
           /// </summary>
           public IActionResult PasswordResetRequest()
           {
               return View();
           }

           /// <summary>
           /// Generates a password reset request for the specified email address.
           /// Accepts the email address posted via the RequestPasswordResetViewModel.
           /// </summary>
           [HttpPost]
           [ValidateAntiForgeryToken]
           public async Task<IActionResult> RequestPasswordReset(PasswordResetRequestViewModel model)
           {
               // Validates the received email address based on the view model
               if (!ModelState.IsValid)
               {
                   return View(model);
               }

               // Gets the user entity for the specified email address
               ApplicationUser user = await userManager.FindByEmailAsync(model.Email);

               if (user != null)
               {
                   // Generates a password reset token for the user
                   string token = await userManager.GeneratePasswordResetTokenAsync(user);

                   // Prepares the URL of the password reset link (targets the "ResetPassword" action)
                   // Fill in the name of your controller
                   string resetUrl = Url.Action(nameof(PasswordResetController.PasswordReset), nameof(PasswordResetController), new { userId = user.Id, token }, Request.Scheme);

                   // Creates and sends the password reset email to the user's address
                   await messageService.SendEmailAsync(user.Email, "Password reset request",
                       $"To reset your account's password, click <a href=\"{resetUrl}\">here</a>");
               }

               // Displays a view asking the visitor to check their email and click the password reset link
               return View("CheckYourEmail");
           }

           /// <summary>
           /// Handles the links that users click in password reset emails.
           /// If the request parameters are valid, displays a form where users can reset their password.
           /// </summary>
           public async Task<IActionResult> PasswordReset(int? userId, string token)
           {
               if (String.IsNullOrEmpty(token))
               {
                   return NotFound();
               }

               ApplicationUser user = await userManager.FindByIdAsync(userId.ToString());

               try
               {
                   // Verifies the parameters of the password reset request
                   // True if the token is valid for the specified user, false if the token is invalid or has expired
                   // By default, the generated tokens are single-use and expire in 1 day
                   if (await userManager.VerifyUserTokenAsync(user, userManager.Options.Tokens.PasswordResetTokenProvider, "ResetPassword", token))
                   {
                       // If the password request is valid, displays the password reset form
                       var model = new PasswordReseViewModel
                       {
                           UserId = userId.Value,
                           Token = token
                       };

                       return View(model);
                   }

                   // If the password request is invalid, returns a view informing the user
                   return View("PasswordResetResult", ViewBag.Success = false);
               }
               catch (InvalidOperationException)
               {
                   // An InvalidOperationException occurs if a user with the given ID is not found
                   // Returns a view informing the user that the password reset request is not valid
                   return View("PasswordResetResult", ViewBag.Success = false);
               }
           }

           /// <summary>
           /// Resets the user's password based on the posted data.
           /// Accepts the user ID, password reset token and the new password via the ResetPasswordViewModel.
           /// </summary>
           [HttpPost]
           [ValidateAntiForgeryToken]
           public async Task<IActionResult> ResetPassword(PasswordReseViewModel model)
           {
               // Validates the received password data based on the view model
               if (!ModelState.IsValid)
               {
                   return View(model);
               }

               bool result = false;

               ApplicationUser user = await userManager.FindByIdAsync(model.UserId.ToString());

               // Changes the user's password if the provided reset token is valid
               if (user != null && (await userManager.ResetPasswordAsync(user, model.Token, model.Password)).Succeeded)
               {
                   // If the password change was successful, displays a message informing the user
                   result = true;
               }

               // Occurs if the reset token is invalid
               // Returns a view informing the user that the password reset failed
               return View("PasswordResetResult", ViewBag.Success = result);            
           }
       }
   }

   ```
7. We recommend creating view models for your password reset actions and input forms:

   - For the reset request form, the view model needs to validate and transfer the email address value.
   - For the password reset form, the view model must contain the user ID, reset token and the new password.

     ```csharp title="Password reset view model example"

     using System.ComponentModel;
     using System.ComponentModel.DataAnnotations;

     namespace LearningKitCore.Models.Users.PasswordReset
     { 
         public class PasswordReseViewModel
         {
             public int UserId
             {
                 get;
                 set;
             }

             public string Token
             {
                 get;
                 set;
             }

             [DataType(DataType.Password)]
             [Required(ErrorMessage = "The Password cannot be empty.")]
             [DisplayName("Password")]
             [MaxLength(100, ErrorMessage = "The Password cannot be longer than 100 characters.")]
             public string Password
             {
                 get;
                 set;
             }

             [DataType(DataType.Password)]
             [DisplayName("Password confirmation")]
             [MaxLength(100, ErrorMessage = "The Password cannot be longer than 100 characters.")]
             [Compare("Password", ErrorMessage = "The entered passwords do not match.")]
             public string PasswordConfirmation
             {
                 get;
                 set;
             }
         }
     }

     ```
8. Design the user interface for the password reset functionality on your website:
   - Add a button or link targeting the _RequestPasswordReset_ action into an appropriate location on your website (for example as a "Forgotten password" link under the sign-in form).
   - Create a view for the  _RequestPasswordReset_  action that displays an email submission form.
   - Create a view that informs users to check their email and click a link to reset their password _(CheckYourEmail_ view in the example).
   - Create a view for the _ResetPassword_ action that displays a password reset form. We recommend using a strongly typed view based on your password reset view model.
   - Create a view for the results of the _ResetPassword_ action (_PasswordResetResult_ in the example).

Users can now reset their passwords on your site. When a user clicks the password reset button or link and submits their email address, the system sends them an email. The email contains a link (single-use with a 1-day expiration by default) that sends the user to a password reset form, where they can set a new password. The password reset form only works for users who access the URL with a valid token parameter.

<!-- dev-model:core end -->
