2-Step Verification with ASP.NET Core Identity

Introduction

Microsoft 2-Step Verification, also known as two-factor authentication (2FA), is a security feature that adds extra protection to your Microsoft account. With 2-Step Verification, you will need to provide two forms of identification to access your account, such as a password and a verification code.

The first form of identification is your password, which is something you know. The second form of identification is a verification code, which is something you have. The verification code can be sent to your phone or email or generated by an authenticator app such as Microsoft Authenticator.

Once you enable 2-Step Verification, you will be required to enter both your password and the verification code every time you sign in to your Microsoft account on a new device or browser. This makes it much more difficult for hackers to gain access to your account, even if they have your password.

2-Step Verification is highly recommended for all Microsoft accounts, especially those that contain sensitive information or are used for business purposes. It is easy to set up and can provide an extra layer of security to protect your personal and professional data.

Prerequisites

  • ASP NET Core
  • C#

To implement 2-Step Verification with Angular and ASP.NET Core Identity, you can follow the below steps:

1. Install the following NuGet packages:

Install-Package Microsoft.AspNetCore.Identity
Install-Package Microsoft.AspNetCore.Identity.EntityFrameworkCore

2. Create a class named "ApplicationUser" that inherits from "IdentityUser" and add the following code:

using Microsoft.AspNetCore.Identity;

public class ApplicationUser : IdentityUser
{
    public string TwoFactorSecretKey { get; set; }
}

3. In the "ConfigureServices" method of "Startup.cs", add the following code:

using Microsoft.AspNetCore.Identity;

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<ApplicationUser, IdentityRole>(options =>
    {
        options.SignIn.RequireConfirmedEmail = true;
        options.User.RequireUniqueEmail = true;
        options.Tokens.EmailConfirmationTokenProvider = "emailconfirmation";
        options.Tokens.ChangeEmailTokenProvider = "emailconfirmation";
        options.Tokens.PasswordResetTokenProvider = "passwordreset";
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
        options.Lockout.MaxFailedAccessAttempts = 5;
    })
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders()
        .AddTokenProvider<EmailConfirmationTokenProvider<ApplicationUser>>("emailconfirmation")
        .AddTokenProvider<ChangeEmailTokenProvider<ApplicationUser>>("emailconfirmation")
        .AddTokenProvider<PasswordResetTokenProvider<ApplicationUser>>("passwordreset")
        .AddUserManager<UserManager<ApplicationUser>>()
        .AddSignInManager<SignInManager<ApplicationUser>>();

    services.ConfigureApplicationCookie(options =>
    {
        options.LoginPath = "/login";
        options.AccessDeniedPath = "/accessdenied";
        options.Cookie.HttpOnly = true;
        options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
        options.SlidingExpiration = true;
    });
}

4. In the "Configure" method of "Startup.cs", add the following code:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller}/{action}/{id?}",
            defaults: new { controller = "home", action = "index" });
    });
}

5. Create a class named "TwoFactorCodeValidator" and add the following code:

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

public class TwoFactorCodeValidator : IUserValidator<ApplicationUser>
{
    private readonly UserManager<ApplicationUser> _userManager;

    public TwoFactorCodeValidator(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }

    public Task<IdentityResult> ValidateAsync(UserManager<ApplicationUser> manager, ApplicationUser user)
    {
        var twoFactorEnabled = _userManager.GetTwoFactorEnabledAsync(user).Result;

        if (!twoFactorEnabled)
        {
            return Task.FromResult(IdentityResult.Success);
        }

        var twoFactorCode = user.TwoFactorSecretKey;

        if (string.IsNullOrEmpty(twoFactorCode))
        {
            return Task.FromResult(IdentityResult.Failed(new IdentityError { Description = "Two factor authentication is enabled but a secret key has not been set." }));
        }

        if (string.IsNullOrEmpty(user.TwoFactorCode))
        {
            return Task.FromResult(IdentityResult.Failed(new IdentityError {

Summary 

This article discussed the two-factor authentication (2FA) implementation in detail.


Recommended Free Ebook
Similar Articles