Implementing Two-Factor Authentication (2FA) in .NET Core Applications
Two-Factor Authentication (2FA) adds an extra layer of security to your application by requiring users to provide two forms of authentication before they can access their accounts. The first factor is typically a password (something the user knows), and the second factor is usually something the user has, such as a smartphone app (e.g., Google Authenticator) or an SMS code.
In ASP.NET Core, you can easily implement 2FA using ASP.NET Core Identity with built-in support for time-based one-time passwords (TOTP), which are commonly used in 2FA systems.
This guide will walk you through implementing 2FA in an ASP.NET Core MVC or Razor Pages application, including the necessary configurations and code.
1. Set Up ASP.NET Core Identity
If you're starting from scratch, make sure that ASP.NET Core Identity is set up for user authentication in your application. Identity handles user management, including login, registration, and 2FA functionality.
1.1. Install Required Packages
Make sure you have these NuGet packages installed for ASP.NET Core Identity:
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
1.2. Add Identity Services
In your Program.cs (or Startup.cs for older versions), configure ASP.NET Core Identity services.
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureServices((context, services) =>
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(context.Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<ApplicationUser>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders(); // Add token providers for 2FA
services.AddRazorPages();
services.AddAuthentication();
});
webBuilder.Configure(app =>
{
var env = app.Environment;
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
});
});
}
Explanation:
AddDefaultTokenProviders() enables ASP.NET Core Identity to generate tokens for actions like email confirmation, password reset, and 2FA.
2. Enable Two-Factor Authentication (2FA)
Once Identity is set up, we can enable 2FA using a combination of Email, SMS, and Authenticator Apps (TOTP).
2.1. Configure 2FA in Startup.cs or Program.cs
Make sure 2FA is enabled for your Identity system by setting up the necessary token providers. This should already be configured when you call AddDefaultTokenProviders().
2.2. User Authentication and 2FA Setup
The next step is to allow users to configure 2FA. This involves setting up the ability for users to either receive 2FA codes via SMS or use TOTP (Authenticator Apps).
Configure TOTP (Authenticator App)
ASP.NET Core supports generating Time-based One-Time Passwords (TOTP) that work with authenticator apps such as Google Authenticator or Microsoft Authenticator.
Generate TOTP Key for User:
You will need to generate a QR code for users to scan with their authenticator app. This QR code is tied to a secret key.
Enable 2FA for User:
The user will enable 2FA during their login process or through their account settings.
3. Implementing 2FA (Authenticator App - TOTP)
3.1. Generate QR Code for Authenticator App
To generate a QR code for the user’s authenticator app, we will use the Totp feature of the Microsoft.AspNetCore.Identity library.
Add 2FA Setup Page: This is where the user will enable 2FA.
[HttpGet]
public async Task<IActionResult> EnableAuthenticator()
{
var user = await _userManager.GetUserAsync(User);
var model = new EnableAuthenticatorViewModel();
// Generate a recovery code and QR code for the authenticator app
var key = await _userManager.GetAuthenticatorKeyAsync(user);
if (string.IsNullOrEmpty(key))
{
await _userManager.ResetAuthenticatorKeyAsync(user);
key = await _userManager.GetAuthenticatorKeyAsync(user);
}
var qrCodeUrl = _urlEncoder.Encode($"otpauth://totp/MyApp:{user.UserName}?secret={key}&issuer=MyApp");
model.QrCodeUrl = qrCodeUrl;
model.SharedKey = key;
return View(model);
}
In this code:
GetAuthenticatorKeyAsync generates a secret key for the user if they don't already have one.
ResetAuthenticatorKeyAsync is used to regenerate a new key if necessary.
qrCodeUrl is a URL that can be encoded into a QR code that users can scan using their authenticator app.
3.2. Generate QR Code Image
Once the QR code URL is generated, we can create an image for the user to scan using a QR code generation library like QRCoder.
Install the QRCoder package:
dotnet add package QRCoder
Then, in the EnableAuthenticator view:
public IActionResult EnableAuthenticator()
{
var qrGenerator = new QRCodeGenerator();
var qrCodeData = qrGenerator.CreateQrCode(model.QrCodeUrl, QRCodeGenerator.ECCLevel.Q);
var qrCode = new QRCode(qrCodeData);
using (var ms = new MemoryStream())
{
qrCode.GetGraphic(20).Save(ms, System.Drawing.Imaging.ImageFormat.Png);
model.QrCodeImage = Convert.ToBase64String(ms.ToArray());
}
return View(model);
}
This generates the QR code image and returns it to the view in Base64 format.
3.3. Verify TOTP (Authenticator App) During Login
When the user logs in and has 2FA enabled, they'll be prompted to enter the TOTP code from their authenticator app. Here's how to verify the code:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> VerifyAuthenticatorCode(string code)
{
var user = await _userManager.GetUserAsync(User);
var isCodeValid = await _userManager.VerifyTwoFactorTokenAsync(user, _userManager.Options.Tokens.AuthenticatorTokenProvider, code);
if (isCodeValid)
{
return RedirectToAction("Index", "Home");
}
ModelState.AddModelError(string.Empty, "Invalid code.");
return View();
}
Here:
VerifyTwoFactorTokenAsync verifies the TOTP code entered by the user against the secret key.
4. Adding SMS-based Two-Factor Authentication
If you'd like to use SMS-based 2FA in addition to the authenticator app, you need to set up an SMS provider like Twilio or SendGrid.
4.1. Configure SMS Provider
Install Twilio or another SMS service provider.
dotnet add package Twilio
In your Startup.cs or Program.cs, configure the SMS provider:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IUserTwoFactorTokenProvider<ApplicationUser>, SmsTokenProvider<ApplicationUser>>();
}
4.2. Sending SMS Codes
You will need to configure your application to send SMS codes using the SendSmsAsync method:
public class SmsTokenProvider : IUserTwoFactorTokenProvider<ApplicationUser>
{
public async Task<string> GenerateAsync(string purpose, UserManager<ApplicationUser> manager, ApplicationUser user)
{
var token = new Random().Next(100000, 999999).ToString();
await SendSmsAsync(user.PhoneNumber, token);
return token;
}
public Task<bool> ValidateAsync(string purpose, string token, UserManager<ApplicationUser> manager, ApplicationUser user)
{
return Task.FromResult(token == expectedToken); // Compare token sent vs received
}
private async Task SendSmsAsync(string phoneNumber, string token)
{
// Integrate with your SMS service, e.g., Twilio
var message = $"Your verification code is {token}";
await _smsService.SendSmsAsync(phoneNumber, message);
}
}
Here, the SmsTokenProvider generates a random code and sends it via SMS to the user’s registered phone number.
5. Handling 2FA Recovery Codes
For users who lose access to their second factor (phone, authenticator app), you should provide recovery codes that they can use to regain access to their account. These recovery codes are one-time-use codes that can be generated and stored securely.
Learn Dot Net Course in Hyderabad
Read More
Role-Based Access Control (RBAC) in .NET Core Applications
Preventing SQL Injection Attacks in Full Stack .NET Development
How to Protect Against Cross-Site Scripting (XSS) in ASP.NET Core
Implementing SSL/TLS in Full Stack .NET Applications
Visit Our Quality Thought Institute in Hyderabad
Subscribe by Email
Follow Updates Articles from This Blog via Email
No Comments