Forgot Password in ASP.NET Core Identity

Forgot Password in ASP.NET Core Identity

In this article, I will discuss how to implement the Forgot Password Functionality in ASP.NET Core Identity. Please read our previous article discussing External Identity Providers in ASP.NET Core Identity.

The “Forget Password” functionality in a web application is a crucial feature for handling situations where users forget their passwords. Let us understand why it’s important and how it works in Web Applications:

  • Improved User Experience: Users often forget their passwords, especially when using multiple applications. Providing a “Forgot Password” option ensures they can reset their password easily without requiring manual support, thus improving overall usability.
  • Enhanced Security: This feature enhances security. When a user forgets their password, they can request a password reset link sent to their registered and confirmed email address. This process ensures that only the legitimate account owner can reset the password.
Reset User Password in ASP.NET Core Identity using Forget Password:

Resetting a user’s password in ASP.NET Core Identity using the Forgot Password feature involves several steps. Let us proceed and see the step-by-step process to implement Reset Password using ASP.NET Core Identity in an ASP.NET Core MVC Application. Let us first understand the workflow, and then we will implement the same.

Forgot Password Button in Login Page:

We need to provide a link named “Forgot Password” on the Login Page, as shown in the image below. This link provides users with a way to reset their password if they cannot recall it. Placing the “Forgot Password?” button on the login page ensures accessibility and improves the user experience. Instead of blocking users who cannot log in, it gives them a recovery option without contacting support.

Forgot Password Button in Login Page

Forgot Password Page:

When the user clicks the link, they are redirected to the Forgot Password page, which asks for their registered email address. This form validates whether the email is associated with an account. The process is intentionally kept simple, just one field and one action: sending the reset link.

Reset User Password in ASP.NET Core Identity using Forget Password

Forgot Password Sent Email Confirmation Page:

After the email is submitted, the application shows a confirmation page regardless of whether the email exists or is confirmed. This approach follows security best practices by avoiding user enumeration (hackers cannot guess which emails are valid). It simply assures the user that if their email exists, they will receive a reset link.

Forgot Password in ASP.NET Core Identity

User Received Password Reset Link (Email):

The system sends a professional-looking email containing a secure reset link. This email usually includes the user’s name for personalization, the reset link, and a note about ignoring the email if they did not request it.

How to implement the Forgot Password Functionality in ASP.NET Core Identity

Reset Password Page:

When the user clicks the reset link, they are taken to the Reset Password page, where they can safely enter a new password and confirm it. This page enforces password rules (length, complexity, etc.) to ensure strong security. It also includes hidden fields for the Email and Token so that the request is tied to the correct account.

Reset Password Page

Password Reset Successful Message:

Once the reset process is completed, the user is shown a success page. This page confirms that their password has been updated successfully and often includes a direct link back to the Login page. This closing step ensures clarity and smooth navigation for the user.

Password Reset Successful Message

How to Implement Forgot Password in ASP.NET Core Identity:

To implement Forget Password in ASP.NET Core Identity, we need to follow the steps below:

  • User Requests Password Reset: The user clicks on the “Forget Password” link and enters their email address.
  • Generate Token: ASP.NET Core Identity generates a secure token that is unique to the user and the current time. This token is often sent via email.
  • Send Email: The system sends an email to the user’s registered email address containing the password reset token and a link to reset the password.
  • User Resets Password: The user clicks on the link, which redirects them to a page where they can set a new password. The page typically asks for the token (either automatically included in the URL or entered manually) and the new password.
  • Validate Token: The system validates the token to ensure it’s valid and corresponds to the user. This validation is crucial for security.
  • Update Password: If the token is valid, the system updates the user’s password with the new one.

Let us proceed and see how we can implement this using ASP.NET Core Identity in our ASP.NET Core MVC Application step by step.

Creating Required View Models:

Let us first create the View Models required for Forgot Password functionalities.

Forgot Password View Model

Create a class file named ForgotPasswordViewModel.cs within the ViewModels folder and then copy and paste the following code. This will be the Model for the ForgotPassword view, where we will ask the user to enter his/her Email address. So, this class contains just one property, i.e., Email.

using System.ComponentModel.DataAnnotations;
namespace ASPNETCoreIdentityDemo.ViewModels
{
    public class ForgotPasswordViewModel
    {
        [Required(ErrorMessage = "Please enter your Email address.")]
        [EmailAddress(ErrorMessage = "The Email address is not valid.")]
        public string Email { get; set; } = null!;
    }
}
Password Reset View Model:

To reset the user password, we need the following

  • Email,
  • Password Reset Token,
  • New Password and
  • Confirm Password

Here, the user needs to provide the new and confirm passwords. Email and reset token are in the password reset link. So, create a class file named ResetPasswordViewModel.cs within the ViewModels folder and copy and paste the following code. This is the model that we will use in our Password Reset View.

using System.ComponentModel.DataAnnotations;
namespace ASPNETCoreIdentityDemo.ViewModels
{
    public class ResetPasswordViewModel
    {
        [Required(ErrorMessage = "Email address is required.")]
        [EmailAddress(ErrorMessage = "Please enter a valid Email address.")]
        public string Email { get; set; } = null!;

        [Required(ErrorMessage = "Password is required.")]
        [DataType(DataType.Password, ErrorMessage = "Invalid Password format.")]
        public string Password { get; set; } = null!;

        [Required(ErrorMessage = "Please confirm your password.")]
        [DataType(DataType.Password, ErrorMessage = "Invalid Password format.")]
        [Display(Name = "Confirm Password")]
        [Compare("Password", ErrorMessage = "Password and Confirm Password must match.")]
        public string ConfirmPassword { get; set; } = null!;

        [Required(ErrorMessage = "The password reset token is required.")]
        public string Token { get; set; } = null!;
    }
}
Extend IEmailService Interface:

Now, we need to add a method to send the Password Reset link. So, please modify the IEmailService interface as follows.

namespace ASPNETCoreIdentityDemo.Services
{
    public interface IEmailService
    {
        Task SendRegistrationConfirmationEmailAsync(string toEmail, string firstName, string confirmationLink);
        Task SendAccountCreatedEmailAsync(string toEmail, string firstName, string loginLink);
        Task SendResendConfirmationEmailAsync(string toEmail, string firstName, string confirmationLink);

        //New Method to send Password Reset Link
        Task SendPasswordResetEmailAsync(string toEmail, string firstName, string resetLink);
    }
}
Extend the Email Service

Now, we need to provide the Implementation for the SendPasswordResetEmailAsync method. So, please add the following code to the EmailService class.

public async Task SendPasswordResetEmailAsync(string toEmail, string firstName, string resetLink)
{
    string html = $@"
            <html><body style='font-family: Arial, sans-serif; background:#f4f6f8; margin:0; padding:20px;'>
              <div style='max-width:600px; margin:auto; background:#fff; padding:30px; border-radius:8px;'>
                <h2 style='color:#333;'>Password Reset Request</h2>
                <p style='font-size:16px; color:#555;'>Hi {firstName},</p>
                <p style='font-size:16px; color:#555;'>We received a request to reset your password. Click the button below to choose a new one.</p>
                <p style='text-align:center;'>
                  <a href='{resetLink}' style='background:#0d6efd; color:#fff; padding:12px 24px; border-radius:6px; text-decoration:none; font-weight:bold;'>Reset Password</a>
                </p>
                <p style='font-size:13px; color:#777;'>If you didn't request this, you can ignore this email.</p>
                <p style='font-size:12px; color:#999; margin-top:30px;'>&copy; {DateTime.UtcNow.Year} Dot Net Tutorials. All rights reserved.</p>
              </div>
            </body></html>";

    await SendEmailAsync(toEmail, "Reset Your Password - Dot Net Tutorials", html, true);
}
Extend IAccountService Interface

Now, we need to include two methods in the IAccountService interface for implementing Forgot Password Functionalities. So, please modify the IAccountService interface as follows:

using ASPNETCoreIdentityDemo.ViewModels;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;

namespace ASPNETCoreIdentityDemo.Services
{
    public interface IAccountService
    {
        //Existing Methods
        Task<IdentityResult> RegisterUserAsync(RegisterViewModel model);
        Task<IdentityResult> ConfirmEmailAsync(Guid userId, string token);
        Task<SignInResult> LoginUserAsync(LoginViewModel model);
        Task LogoutUserAsync();
        Task SendEmailConfirmationAsync(string email);
        Task<ProfileViewModel> GetUserProfileByEmailAsync(string email);

        //New Methods for External Login
        AuthenticationProperties ConfigureExternalLogin(string provider, string? redirectUrl);
        Task<ExternalLoginInfo?> GetExternalLoginInfoAsync();
        Task<SignInResult> ExternalLoginSignInAsync(string loginProvider, string providerKey, bool isPersistent);
        Task<IdentityResult> CreateExternalUserAsync(ExternalLoginInfo info);

        //New Methods for Forgot Password
        Task<bool> SendPasswordResetLinkAsync(string email);
        Task<IdentityResult> ResetPasswordAsync(ResetPasswordViewModel model);
    }
}
Extend the Account Service

Now, we need to provide the Implementation for the two new methods. So, please add the following two methods to the AccountService class.

SendPasswordResetLinkAsync

This method is used when a user requests to reset their password through the Forgot Password feature. It verifies whether the provided email exists in the system, generates a secure password reset token using ASP.NET Core Identity, and creates a reset link containing both the token and the email address. The link is then sent to the user via email, allowing them to continue the password reset process securely.

public async Task<bool> SendPasswordResetLinkAsync(string email)
{
    // Try to find the user by their email address
    var user = await _userManager.FindByEmailAsync(email);

    // Security measure: 
    // Do not reveal whether the user exists or not — 
    // always behave the same if the user is not found or the email is not confirmed
    if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
        return false;

    // Generate a unique, secure token for password reset
    var token = await _userManager.GeneratePasswordResetTokenAsync(user);

    // Encode the token so it can be safely used in a URL
    var encodedToken = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(token));

    // Construct the password reset link with the encoded token and user’s email
    var baseUrl = _configuration["AppSettings:BaseUrl"];
    var resetLink = $"{baseUrl}/Account/ResetPassword?email={user.Email}&token={encodedToken}";

    // Send the reset link via email to the user
    await _emailService.SendPasswordResetEmailAsync(user.Email!, user.FirstName, resetLink);

    return true;
}
ResetPasswordAsync

This method is called after the user clicks the reset link from their email and submits a new password. It validates the reset token and updates the user’s password in the system by calling the Identity framework’s ResetPasswordAsync method. If the process succeeds, the user can log in with their new password; otherwise, appropriate error messages are returned.

public async Task<IdentityResult> ResetPasswordAsync(ResetPasswordViewModel model)
{
    // Find the user associated with the provided email
    var user = await _userManager.FindByEmailAsync(model.Email);

    // If user not found, return a generic failure (no details leaked for security)
    if (user == null)
        return IdentityResult.Failed(new IdentityError { Description = "Invalid request." });

    // Decode the token that was passed in from the reset link
    var decodedBytes = WebEncoders.Base64UrlDecode(model.Token);
    var decodedToken = Encoding.UTF8.GetString(decodedBytes);

    // Attempt to reset the user's password with the new one
    var result = await _userManager.ResetPasswordAsync(user, decodedToken, model.Password);

    // If successful, update the Security Stamp to invalidate any active sessions or tokens
    if (result.Succeeded)
        await _userManager.UpdateSecurityStampAsync(user);

    return result;
}
Add Controller Actions

Now, we need to include the following four action methods within the Account Controller.

ForgotPassword (GET)

This method returns the Forgot Password page, where the user can enter their registered email address to request a password reset. It ensures that the page is loaded fresh, without any pre-filled or sensitive data.

// GET: ForgotPassword
[HttpGet]
public IActionResult ForgotPassword()
{
    return View();
}
ForgotPassword (POST)

This method handles the form submission for the Forgot Password request. When a user submits their email, it triggers the password reset process by calling the service method that generates a reset token and sends an email with the reset link. For security reasons, it always displays a confirmation page, without revealing whether the email exists in the system.

// POST: ForgotPassword
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
    if (!ModelState.IsValid)
        return View(model);

    await _accountService.SendPasswordResetLinkAsync(model.Email);

    // Always show confirmation view (don’t reveal if email exists)
    return View("ForgotPasswordConfirmation");
}
ResetPassword (GET)

This method is responsible for loading the Reset Password page when a user clicks the link from their email. It validates that both email and token are present in the request and then passes them to the ResetPassword view model so the user can securely enter a new password.

// GET: ResetPassword
[HttpGet]
public IActionResult ResetPassword(string email, string token)
{
    if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(token))
        return BadRequest("Invalid password reset request.");

    return View(new ResetPasswordViewModel { Email = email, Token = token });
}
ResetPassword (POST)

This method processes the form submission for setting a new password. It validates the input, confirms the reset token through the service, and if successful, updates the user’s password and invalidates any old sessions. On success, it shows a confirmation page; on failure, it redisplays the form with relevant error messages.

// POST: ResetPassword
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ResetPassword(ResetPasswordViewModel model)
{
    if (!ModelState.IsValid)
        return View(model);

    var result = await _accountService.ResetPasswordAsync(model);
    if (result.Succeeded)
        return View("ResetPasswordConfirmation");

    foreach (var error in result.Errors)
        ModelState.AddModelError("", error.Description);

    return View(model);
}
Creating and Updating Views:

Now, we will modify the Login view to include the Forgot password link, and also, we will create four additional views for Forgot Password Management.

Modifying Login View:

Please modify the Login.cshtml view as follows:

@model ASPNETCoreIdentityDemo.ViewModels.LoginViewModel
@{
ViewData["Title"] = "Login";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="container-xxl pt-3 pb-4">
<div class="row justify-content-center">
<div class="col-12 col-lg-11 col-xl-10 col-xxl-10">
<div class="card border-0 shadow-lg rounded-4 overflow-hidden">
<div class="row g-0">
<!-- Left: Login Section -->
<div class="col-md-6 bg-light d-flex align-items-center">
<div class="w-100 p-4 p-lg-5">
<h3 class="mb-2 text-center fw-bold text-primary">
Sign in to <span class="text-dark">Dot Net Tutorials</span>
</h3>
<p class="text-center text-muted mb-4 small">
<span class="fw-semibold text-secondary">Welcome back!</span>
Please enter your credentials below to access your account.
</p>
<form asp-action="Login" method="post" novalidate>
<!-- Messages Section -->
@if (!ViewData.ModelState.IsValid)
{
<div class="alert alert-danger alert-dismissible fade show small" role="alert">
<strong>Please fix the errors below and try again:</strong>
<div asp-validation-summary="All" class="mb-0 mt-1"></div>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
}
<input type="hidden" name="ReturnUrl" value="@Model.ReturnURL" />
<div class="mb-3">
<label asp-for="Email" class="form-label fw-semibold text-primary"></label>
<input asp-for="Email" class="form-control" placeholder="Enter your Email Address" autocomplete="username" />
<span asp-validation-for="Email" class="text-danger small"></span>
</div>
<div class="mb-3">
<label asp-for="Password" class="form-label fw-semibold text-primary"></label>
<input asp-for="Password" class="form-control" type="password" placeholder="Enter Your Password" autocomplete="current-password" />
<span asp-validation-for="Password" class="text-danger small"></span>
</div>
<!-- Remember + Forgot -->
<div class="d-flex justify-content-between align-items-center mb-3">
<div class="form-check">
<input asp-for="RememberMe" class="form-check-input" />
<label asp-for="RememberMe" class="form-check-label small"></label>
</div>
<div>
<a asp-action="ForgotPassword" class="text-decoration-none small text-primary fw-semibold">
Forgot your password?
</a>
</div>
</div>
<button type="submit" class="btn btn-primary w-100 fw-semibold py-2 mb-2">Sign In</button>
<p class="mt-3 text-center mb-1">
<span class="text-secondary small">New to <span class="fw-semibold text-dark">Dot Net Tutorials</span>?</span>
<a asp-action="Register" class="text-primary ms-1 text-decoration-none fw-semibold">Create an account</a>
</p>
<p class="text-center mb-0">
<a asp-action="ResendEmailConfirmation" class="text-info text-decoration-none small">Resend email confirmation</a>
</p>
</form>
</div>
</div>
<!-- Right: External Authentication -->
<div class="col-md-6 bg-white d-flex align-items-center">
<div class="w-100 p-4 p-lg-5 d-flex flex-column align-items-center">
<div class="w-100" style="max-width: 340px;">
<h5 class="mb-3 fw-bold text-primary text-center">Quick sign-in</h5>
<div class="mb-3 text-center text-muted small">Use your social account for instant access:</div>
<div class="d-grid gap-3 mb-3">
<a asp-controller="Account" asp-action="ExternalLogin" asp-route-provider="Google"
class="btn btn-outline-primary d-flex align-items-center justify-content-center fw-semibold">
<img src="https://img.icons8.com/color/32/000000/google-logo.png" class="me-2" style="width:24px" alt="Google" />
Google
</a>
<a asp-controller="Account" asp-action="ExternalLogin" asp-route-provider="Facebook"
class="btn d-flex align-items-center justify-content-center fw-semibold"
style="background-color: #3b5998; color: #fff;">
<img src="https://img.icons8.com/fluency/32/000000/facebook-new.png" class="me-2" style="width:24px" alt="Facebook" />
Facebook
</a>
<a href="#" class="btn btn-outline-dark d-flex align-items-center justify-content-center fw-semibold">
<img src="https://img.icons8.com/ios-filled/32/000000/github.png" class="me-2" style="width:24px" alt="GitHub" />
GitHub
</a>
<a href="#" class="btn d-flex align-items-center justify-content-center fw-semibold"
style="background-color: #0078d4; color: #fff;">
<img src="https://img.icons8.com/color/32/000000/microsoft.png" class="me-2" style="width:24px" alt="Microsoft" />
Microsoft
</a>
</div>
<div class="text-center text-muted small mt-4 mb-2">
<span>We never post anything without your permission.</span>
</div>
<hr class="mb-2" />
<div class="text-center text-muted small">
Need help? <a href="mailto:support@dotnettutorials.net" class="text-decoration-none fw-semibold">Contact Support</a>
</div>
</div>
</div>
</div>
<!-- End right -->
</div>
</div>
</div>
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
Creating ForgotPassword View

Create a View named ForgotPassword.cs within the Views/Account folder, then copy and paste the following code.

@model ASPNETCoreIdentityDemo.ViewModels.ForgotPasswordViewModel
@{
ViewData["Title"] = "Forgot Password";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="container d-flex justify-content-center align-items-center mt-5">
<div class="card shadow-lg border-0 rounded-4" style="max-width:500px; width:100%;">
<div class="card-body p-4">
<div class="text-center mb-3">
<i class="bi bi-lock-fill text-primary" style="font-size:2.5rem;"></i>
<h4 class="fw-bold mt-2">Forgot Your Password?</h4>
<p class="text-muted small">No worries! Just enter your registered email and we’ll send you a secure link to reset your password.</p>
</div>
<!-- Success / Info Message -->
@if (ViewBag.Message != null)
{
<div class="alert alert-info alert-dismissible fade show small text-center" role="alert">
@ViewBag.Message
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
}
<!-- Validation Errors -->
@if (!ViewData.ModelState.IsValid)
{
<div class="alert alert-danger alert-dismissible fade show small" role="alert">
<strong>Please correct the following:</strong>
<ul class="mb-0 mt-2">
@foreach (var error in ViewData.ModelState.Values.SelectMany(v => v.Errors))
{
<li>@error.ErrorMessage</li>
}
</ul>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
}
<form asp-action="ForgotPassword" method="post" novalidate>
<div class="mb-3">
<label asp-for="Email" class="form-label fw-semibold"></label>
<input asp-for="Email" class="form-control" placeholder="Enter your email address" autocomplete="email" />
<span asp-validation-for="Email" class="text-danger small"></span>
</div>
<button type="submit" class="btn btn-primary w-100 fw-semibold py-2">Send Reset Link</button>
</form>
<div class="text-center mt-3">
<a asp-action="Login" class="text-decoration-none small fw-semibold text-primary">
<i class="bi bi-arrow-left"></i> Back to Login
</a>
</div>
</div>
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
Creating ForgotPasswordConfirmation View

Create a View named ForgotPasswordConfirmation.cs within the Views/Account folder, then copy and paste the following code.

@{
ViewData["Title"] = "Password Reset Link Sent";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="container d-flex justify-content-center align-items-center mt-5">
<div class="card shadow-lg border-0 rounded-4 p-4 text-center" style="max-width:500px;">
<div class="mb-3">
<i class="bi bi-envelope-check text-success" style="font-size:3rem;"></i>
</div>
<h4 class="fw-bold text-success">Check Your Email</h4>
<p class="text-muted">
If your email is registered with us, a <strong>password reset link</strong> has been sent.
Please check your inbox (and spam folder).
</p>
<a asp-action="Login" class="btn btn-primary px-4 fw-semibold">Go to Login</a>
</div>
</div>
Creating ResetPassword View

Create a View named ResetPassword.cs within the Views/Account folder, then copy and paste the following code.

@model ASPNETCoreIdentityDemo.ViewModels.ResetPasswordViewModel
@{
ViewData["Title"] = "Reset Password";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="container d-flex justify-content-center align-items-center mt-4">
<div class="card shadow-lg border-0 rounded-4" style="max-width:620px; width:100%;">
<div class="card-body p-4">
<div class="text-center mb-3">
<h4 class="fw-bold mt-2">Reset Your Password</h4>
<p class="text-muted small">Enter and confirm your new password. Your account security is our top priority.</p>
</div>
<!-- Success / Info Message -->
@if (ViewBag.Message != null)
{
<div class="alert alert-info alert-dismissible fade show small text-center" role="alert">
@ViewBag.Message
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
}
<!-- Validation Errors -->
@if (!ViewData.ModelState.IsValid)
{
<div class="alert alert-danger alert-dismissible fade show small" role="alert">
<strong>Please fix the following issues:</strong>
<ul class="mb-0 mt-2">
@foreach (var error in ViewData.ModelState.Values.SelectMany(v => v.Errors))
{
<li>@error.ErrorMessage</li>
}
</ul>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
}
<form asp-action="ResetPassword" method="post" novalidate>
<input type="hidden" asp-for="Email" />
<input type="hidden" asp-for="Token" />
<div class="mb-3">
<label asp-for="Password" class="form-label fw-semibold"></label>
<input asp-for="Password" class="form-control" type="password" placeholder="Enter new password" autocomplete="new-password" />
<span asp-validation-for="Password" class="text-danger small"></span>
</div>
<div class="mb-3">
<label asp-for="ConfirmPassword" class="form-label fw-semibold"></label>
<input asp-for="ConfirmPassword" class="form-control" type="password" placeholder="Confirm new password" autocomplete="new-password" />
<span asp-validation-for="ConfirmPassword" class="text-danger small"></span>
</div>
<button type="submit" class="btn btn-success w-100 fw-semibold py-2">✅ Reset Password</button>
</form>
<div class="text-center mt-3">
<a asp-action="Login" class="text-decoration-none small fw-semibold text-primary">
<i class="bi bi-arrow-left"></i> Back to Login
</a>
</div>
</div>
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
Creating ResetPasswordConfirmation View

Create a View named ResetPasswordConfirmation.cs within the Views/Account folder, then copy and paste the following code.

@{
ViewData["Title"] = "Password Reset Successful";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="container d-flex justify-content-center align-items-center mt-5">
<div class="card shadow-lg border-0 rounded-4 p-4 text-center" style="max-width:500px;">
<div class="mb-3">
<i class="bi bi-check-circle-fill text-success" style="font-size:3rem;"></i>
</div>
<h4 class="fw-bold text-success">Password Reset Successful</h4>
<p class="text-muted">Your password has been updated successfully. You can now log in with your new credentials.</p>
<a asp-action="Login" class="btn btn-primary px-4 fw-semibold">Login</a>
</div>
</div>

This is how we can implement Forgot Password functionality to Reset User passwords in ASP.NET Identity. Now, run the application and test the functionality, and it should work as expected.

Note: You can observe that the tokens (Password Reset) are not stored in the UserTokens table. So, in the next session, I will discuss why the Forgot Password and Email Confirmation tokens are not stored in the database table, and then we will see how to store those tokens in the UserTokens table.

In the next article, I will discuss how to Store Tokens in ASP.NET Core IdentityIn this article, I explain how to implement the Forgot Password Functionality in ASP.NET Core Identity. I hope you enjoy this article, Forgot Password in ASP.NET Core Identity.

1 thought on “Forgot Password in ASP.NET Core Identity”

  1. blank

    Building Forgot Password in ASP.NET Core Identity? I’ve just published a step-by-step video covering secure token generation, email reset link, the Reset Password form with validation, and key security best practices in .NET 8. Watch it here 👉 https://youtu.be/uBBAyDR0nUQ
    It pairs perfectly with this guide and will help you implement the feature more quickly and safely.

Leave a Reply

Your email address will not be published. Required fields are marked *