Part-4 | Asp.Net Core Identity Series[.NET 7] | Sending Two-Factor Authentication(2FA) Code To Phone
The main objectives of this article are:
In the next article, we are going to implement Google Authentication.
- Sending Two-Factor Authentication(2FA) Code to Phone
Enable Phone 2FA:
In the Asp.Net Core Identity application to enable 'Phone' Two-Factor Authentication, ensure our 'AspNetUser' table following fields has appropriate data:
- PhoneNumber - Should have valid phone number along with country code
- PhoneNumberConfirmed - must be true
- TwoFactorEnabled - must be true
Twilio Setup:
Twilio is a third-party service provider which provides services like SMS, Voice Calls, Chats, etc.
(Step 1) Go to the Twilio website 'https://www.twilio.com/' and SignUp.
(Step 2) Now Login => We entered into the Twilio console dashboard => Here create a project and you will get 'Account SID', 'Auth Token', and 'My Twilio Phone Number(which will be our From Phone Number).
(Step 3) I'm going to use the Free credits to set up the SMS service. So here is one limitation with free credits we have to register all testing 'To Phone Numbers'
Configure Twilio Settings:
Let's configure the Twilio settings into the 'appsetting.Development.json'.
appsettings.Development.json:
"TwilioSettings":{ "AccountSId":"", "AuthToken":"", "FromPhoneNumber":"" }Let's create a new class like 'TwilioSettings' in the 'Settings' folder.
Settings/TwilioSettings.cs:
namespace RazorPage.AspNetIdentity.Settings; public class TwilioSettings { public string AccountSId{get;set;} public string AuthToken{get;set;} public string FromPhoneNumber{get;set;} }Now let's map the 'TwilioSettings' class with json settings in 'Program.cs'
Program.cs:
builder.Services.Configure<TwilioSettings>(builder.Configuration.GetSection("TwilioSettings"));
Install Twilio NuGet Package:
Let's install the Twilio NuGet Package in our application
Visual Studio 2022:
Install-Package Twilio.AspNet.Core -Version 8.0.0
Visual Studio Code:
dotnet add package Twilio.AspNet.Core --version 8.0.0
Implement SMS Logic:
Let's create a service interface like 'ISMSSenderService.cs'
Services/ISMSSenderService.cs:
namespace RazorPage.AspNetIdentity.Services; public interface ISMSSenderService { Task SendSmsAsync(string number, string message); }Let's create a service file like 'SMSSenderService.cs'
Services/SMSSenderService.cs
using Microsoft.AspNetCore.Identity.UI.Services; using Microsoft.Extensions.Options; using RazorPage.AspNetIdentity.Settings; using Twilio; using Twilio.Rest.Api.V2010.Account; namespace RazorPage.AspNetIdentity.Services; public class SMSSenderService : ISMSSenderService { private readonly TwilioSettings _twilioSettings; public SMSSenderService(IOptions<TwilioSettings> twilioSettins) { _twilioSettings = twilioSettins.Value; } public async Task SendSmsAsync(string number, string message) { TwilioClient.Init(_twilioSettings.AccountSId,_twilioSettings.AuthToken); await MessageResource.CreateAsync( to:number, from: _twilioSettings.FromPhoneNumber, body: message ); } }
- (Line: 11-15) Injecting the TwilioSettings.
- (Line: 18) Here 'Twilio.TwilioClient.Int()' method we pass our 'AccountSId', 'AuthToken'.
- (LIne: 19-23) Here 'MessageResource.CreateAsync' method configured with 'to phonenumber', 'from phone number'.
Program.cs:
builder.Services.AddScoped<ISMSSenderService,SMSSenderService>();
Invoke SMS From Two-Factor Authentication Page:
Let's create a new property like 'TwoFactAuthProviderName' in 'InputModel'.
/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs:
/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs:
public async Task<IActionResult> OnGetAsync(bool rememberMe, string returnUrl = null) { // Ensure the user has gone through the username & password screen first var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); if (user == null) { throw new InvalidOperationException($"Unable to load two-factor authentication user."); } var providers = await _userManager.GetValidTwoFactorProvidersAsync(user); if(providers.Any(_ => _ == "Phone")) { Input.TWoFactAuthProviderName = "Phone"; var token = await _userManager.GenerateTwoFactorTokenAsync(user, "Phone"); await _smsSenderService.SendSmsAsync(user.PhoneNumber, $"OTP Code: ${token}"); } else if (providers.Any(_ => _ == "Email")) { Input.TWoFactAuthProviderName = "Email"; var token = await _userManager.GenerateTwoFactorTokenAsync(user, "Email"); await _emailSender.SendEmailAsync(user.Email, "2FA Code", $"<h3 >{token}</h3>."); } else { throw new InvalidOperationException($"Unable to load two-factor authentication user."); } ReturnUrl = returnUrl; RememberMe = rememberMe; return Page(); }
- (Line: 13) Here we checking whether the 'phone' provider is enabled or not.
- (Line: 15) Here we assign the provider value to the 'TwoFactAuthProviderName'.
- (Line: 16) Here generating the code for the 'phone' provider.
- (Line: 17) Here sending the 2FA code in SMS
/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs:
public async Task<IActionResult> OnPostAsync(bool rememberMe, string returnUrl = null) { if (!ModelState.IsValid) { return Page(); } returnUrl = returnUrl ?? Url.Content("~/"); var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); if (user == null) { throw new InvalidOperationException($"Unable to load two-factor authentication user."); } var authenticatorCode = Input.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty); //var result = await _signInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, rememberMe, Input.RememberMachine); var result = await _signInManager.TwoFactorSignInAsync(Input.TWoFactAuthProviderName, authenticatorCode, rememberMe, Input.RememberMachine); var userId = await _userManager.GetUserIdAsync(user); if (result.Succeeded) { _logger.LogInformation("User with ID '{UserId}' logged in with 2fa.", user.Id); return LocalRedirect(returnUrl); } else if (result.IsLockedOut) { _logger.LogWarning("User with ID '{UserId}' account locked out.", user.Id); return RedirectToPage("./Lockout"); } else { _logger.LogWarning("Invalid authenticator code entered for user with ID '{UserId}'.", user.Id); ModelState.AddModelError(string.Empty, "Invalid authenticator code."); return Page(); } }
- (Line: 19) The provider name value accessing from the 'Input.TwoFActAuthProviderName'.
/Areas/Identity/Pages/Account/LoginWith2fa.cshtml
<input asp-for="Input.TWoFactAuthProviderName" type="hidden" />
In the next article, we are going to implement Google Authentication.
Support Me!
Buy Me A Coffee
PayPal Me
Video Session:
Wrapping Up:
Hopefully, I think this article delivered some useful information on the Asp.Net Core Identity In Razor Pages. using I love to have your feedback, suggestions, and better techniques in the comment section below
Refer:
Part-2 | Asp.Net Core Identity Series[.NET 7] | Registration Email Confirmation
Part-3 | Asp.Net Core Identity Series[.NET 7] | Sending Two-Factor Authentication(2FA) Code To Email
Part-5 | Asp.Net Core Identity Series[.NET 7] | Google Authentication
Part-3 | Asp.Net Core Identity Series[.NET 7] | Sending Two-Factor Authentication(2FA) Code To Email
Part-5 | Asp.Net Core Identity Series[.NET 7] | Google Authentication
Part - 6 | Asp.Net Core Identity Series[.NET 7] | Facebook Authentication
Part - 7 | Asp.Net Core Identity Series[.NET 7] | Twitter Authentication
Part - 7 | Asp.Net Core Identity Series[.NET 7] | Twitter Authentication
Comments
Post a Comment