How to perform Email Confirmation of Users in ASP.NET Core Identity

How to perform Email Confirmation of Users in ASP.NET Core Identity

Email Confirmation is an important part of the user registration process. It allows verifying the registered user is indeed an owner of the provided email. ASP.NET Core Identity also provides the option to enable email confirmation during the time of user registration process.

Do check my previous tutorial – Two-Factor Authentication in ASP.NET Core Identity

Enabling Email Confirmation in Startup class

Inside the ConfigureServices() method of Startup.cs class you can use the IdentityOptions class to initialize the RequireConfirmedEmail to true. This will enable email confirmation in Identity. I have highlighted this line in the below code of the ConfigureServices() method.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<AppIdentityDbContext>(options => options.UseSqlServer(Configuration["ConnectionStrings:DefaultConnection"]));
    services.AddIdentity<AppUser, IdentityRole>().AddEntityFrameworkStores<AppIdentityDbContext>().AddDefaultTokenProviders();

    services.Configure<IdentityOptions>(opts =>
    {
        opts.User.RequireUniqueEmail = true;
        opts.Password.RequiredLength = 8;
        
        opts.SignIn.RequireConfirmedEmail = true;
    });

    services.AddControllersWithViews();
}

The Identity database table called AspNetUsers contains a column called EmailConfirmed which keeps a track on whether an email of a user is confirmed or not. Confirmed ones have the value true while unconfirmed emails have false.

See the below image of the AspNetUsers table where I have shown the EmailConfirmed column’s values.

email confirmed column

Implementing Email Confirmation in Identity

During the time of User Registration process you should add the Email Confirmation procedure. I wrote an article on Creation, Reading, Updation & Deletion of Identity Users. Now I will update the Create action of Admin Controller to include the Email Confirmation functionality.

I have highlighted the code of the Create action of Admin Controller which brings out the email confirmation functionality.

[HttpPost]
public async Task<IActionResult> Create(User user)
{
    if (ModelState.IsValid)
    {
        AppUser appUser = new AppUser
        {
            UserName = user.Name,
            Email = user.Email
        };

        IdentityResult result = await userManager.CreateAsync(appUser, user.Password);
        if (result.Succeeded)
        {
            var token = await userManager.GenerateEmailConfirmationTokenAsync(appUser);
            var confirmationLink = Url.Action("ConfirmEmail", "Email", new { token, email = user.Email }, Request.Scheme);
            EmailHelper emailHelper = new EmailHelper();
            bool emailResponse = emailHelper.SendEmail(user.Email, confirmationLink);
            
            if (emailResponse)
                return RedirectToAction("Index");
            else
            {
                // log email failed 
            }
        }
        else
        {
            foreach (IdentityError error in result.Errors)
                ModelState.AddModelError("", error.Description);
        }
    }
    return View(user);
}
Explanation

The code to look out here is:

var token = await userManager.GenerateEmailConfirmationTokenAsync(appUser);
var confirmationLink = Url.Action("ConfirmEmail", "Email", new { token, email = user.Email }, Request.Scheme);
EmailHelper emailHelper = new EmailHelper();
bool emailResponse = emailHelper.SendEmail(user.Email, confirmationLink);

First I used the GenerateEmailConfirmationTokenAsync() method of UserManager class to generate the email confirmation token for the user who is being created.

Next I generated the confirmation link with the code var confirmationLink = Url.Action("ConfirmEmail", "Email", new { token, email = user.Email }, Request.Scheme). This link will be send to the user’s email account. Clearly you can see the link point to the ConfirmEmail action of the Email controller. The token and email will be added to the link as query string values. The email Controller’s ConfirmEmail action will get their values through Model Binding feature of ASP.NET Core.

Sending Email with SMTP

The next part deals with sending the confirmation email to the user. The 2 lines of code given below create an object of EmailHelper class and then calls the SendEmail() method in order to send the confirmation email to the user.

EmailHelper emailHelper = new EmailHelper();
bool emailResponse = emailHelper.SendEmail(user.Email, confirmationLink);

So create a new folder called Email in the project root and create a class called EmailHelper.cs in it. This class will be sending the email using SMTP. The code of this class is given below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Mail;
using System.Threading.Tasks;

namespace Identity.Email
{
    public class EmailHelper
    {
        public bool SendEmail(string userEmail, string confirmationLink)
        {
            MailMessage mailMessage = new MailMessage();
            mailMessage.From = new MailAddress("[email protected]");
            mailMessage.To.Add(new MailAddress(userEmail));

            mailMessage.Subject = "Confirm your email";
            mailMessage.IsBodyHtml = true;
            mailMessage.Body = confirmationLink;

            SmtpClient client = new SmtpClient();
            client.Credentials = new System.Net.NetworkCredential("[email protected]", "yourpassword");
            client.Host = "smtpout.secureserver.net";
            client.Port = 80;

            try
            {
                client.Send(mailMessage);
                return true;
            }
            catch (Exception ex)
            {
                // log exception
            }
            return false;
        }
    }
}
I have also written a tutorial on How to send HTML Emails with Attachments. You will find it quite useful.

Performing Email Confirmation

To perform the Email Confirmation once the user clicks the confirm link on his/her email, I have to create the Email Controller with it’s ConfirmEmail action method. It’s full code is given below.

using System.Threading.Tasks;
using Identity.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;

namespace Identity.Controllers
{
    public class EmailController : Controller
    {
        private UserManager<AppUser> userManager;
        public EmailController(UserManager<AppUser> usrMgr)
        {
            userManager = usrMgr;
        }

        public async Task<IActionResult> ConfirmEmail(string token, string email)
        {
            var user = await userManager.FindByEmailAsync(email);
            if (user == null)
                return View("Error");

            var result = await userManager.ConfirmEmailAsync(user, token);
            return View(result.Succeeded ? "ConfirmEmail" : "Error");
        }
    }
}

To support this controller I need to add 2 views inside the Views ➤ Email folder these Views are:

1. ConfirmEmail.cshtml
@{
    ViewData["Title"] = "ConfirmEmail";
}

<h1>Confirm Email</h1>
<p>
    Thank you for confirming your email.
</p>
2. Error.cshtml
@{
    ViewData["Title"] = "Error";
}

<h1 class="text-danger">Error</h1>
<h2 class="text-danger">An error occurred while processing your request. Please try again later.</h2>

Testing the Email Confirmation

I create a new user as shown by the below image:

creating new user in Identity

Next I check my email inbox and find the confirmation email. The screenshot of confirmation email is given below:

confirmation email

On clicking the confirmation email link I am redirected to the project and my email gets confirmed. See the below screenshot.

email confirmed

Next I confirm this in AspNetUsers table of Identity database. I find EmailConfirmed column’s values as true which proves my created account’s email is confirmed by Identity. See below image.

email confirmed in AspNetUsers

Modifying the Login Action to Support Email Confirmation

Identity will not let an unconfirmed email user to log in to the application. So you should notify the user about email confirmation error during login.

The UserManager class has a method called IsEmailConfirmedAsync() which tells whether the email is confirmed or not. I used this method in the Login action of Account controller to provide this message to the user during login time. See the highlighted code below.

[HttpPost]
 [AllowAnonymous]
 [ValidateAntiForgeryToken]
 public async Task<IActionResult> Login(Login login)
 {
     if (ModelState.IsValid)
     {
         AppUser appUser = await userManager.FindByEmailAsync(login.Email);
         if (appUser != null)
         {
             await signInManager.SignOutAsync();
             Microsoft.AspNetCore.Identity.SignInResult result = await signInManager.PasswordSignInAsync(appUser, login.Password, false, false);
             if (result.Succeeded)
                 return Redirect(login.ReturnUrl ?? "/");

             bool emailStatus = await userManager.IsEmailConfirmedAsync(appUser);
             if (emailStatus == false)
             {
                 ModelState.AddModelError(nameof(login.Email), "Email is unconfirmed, please confirm it first");
             }
         }
         ModelState.AddModelError(nameof(login.Email), "Login Failed: Invalid Email or password");
     }
     return View(login);
 }

You can download the full codes of this tutorial from the below link:

Download

Conclusion

You have covered all the things that are required for successful email confirmation in ASP.NET Core Identity.

Share this article -

yogihosting

ABOUT THE AUTHOR

This article has been written by the Technical Staff of YogiHosting. Check out other articles on "ASP.NET Core, jQuery, EF Core, SEO, jQuery, HTML" and more.

Leave a Reply

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