From 1a5fe8230e2b17d476cc127c1e6eb7bea30c5d5c Mon Sep 17 00:00:00 2001 From: Abdullah Atta Date: Sat, 9 Sep 2023 20:30:35 +0500 Subject: [PATCH] identity: move to twilio verify for SMS 2FA --- Streetwriters.Common/Constants.cs | 5 ++- .../Interfaces/ISMSSender.cs | 4 +- Streetwriters.Identity/Services/MFAService.cs | 4 +- Streetwriters.Identity/Services/SMSSender.cs | 43 +++++++++++++------ .../Streetwriters.Identity.csproj | 1 + 5 files changed, 37 insertions(+), 20 deletions(-) diff --git a/Streetwriters.Common/Constants.cs b/Streetwriters.Common/Constants.cs index e7be902..2425b73 100644 --- a/Streetwriters.Common/Constants.cs +++ b/Streetwriters.Common/Constants.cs @@ -45,8 +45,9 @@ namespace Streetwriters.Common public static string NOTESNOOK_API_SECRET => Environment.GetEnvironmentVariable("NOTESNOOK_API_SECRET"); // MessageBird is used for SMS sending - public static string MESSAGEBIRD_ACCESS_KEY => Environment.GetEnvironmentVariable("MESSAGEBIRD_ACCESS_KEY"); - + public static string TWILIO_ACCOUNT_SID => Environment.GetEnvironmentVariable("TWILIO_ACCOUNT_SID"); + public static string TWILIO_AUTH_TOKEN => Environment.GetEnvironmentVariable("TWILIO_AUTH_TOKEN"); + public static string TWILIO_SERVICE_SID => Environment.GetEnvironmentVariable("TWILIO_SERVICE_SID"); // Server discovery public static int NOTESNOOK_SERVER_PORT => int.Parse(Environment.GetEnvironmentVariable("NOTESNOOK_SERVER_PORT")); public static string NOTESNOOK_SERVER_HOST => Environment.GetEnvironmentVariable("NOTESNOOK_SERVER_HOST"); diff --git a/Streetwriters.Identity/Interfaces/ISMSSender.cs b/Streetwriters.Identity/Interfaces/ISMSSender.cs index 8522727..7298ab2 100644 --- a/Streetwriters.Identity/Interfaces/ISMSSender.cs +++ b/Streetwriters.Identity/Interfaces/ISMSSender.cs @@ -24,7 +24,7 @@ namespace Streetwriters.Identity.Interfaces { public interface ISMSSender { - string SendOTP(string number, IClient client); - bool VerifyOTP(string id, string code); + Task SendOTPAsync(string number, IClient client); + Task VerifyOTPAsync(string id, string code); } } \ No newline at end of file diff --git a/Streetwriters.Identity/Services/MFAService.cs b/Streetwriters.Identity/Services/MFAService.cs index af61907..ece153f 100644 --- a/Streetwriters.Identity/Services/MFAService.cs +++ b/Streetwriters.Identity/Services/MFAService.cs @@ -161,7 +161,7 @@ namespace Streetwriters.Identity.Services break; case "sms": await UserManager.SetPhoneNumberAsync(user, form.PhoneNumber); - var id = SMSSender.SendOTP(form.PhoneNumber, client); + var id = await SMSSender.SendOTPAsync(form.PhoneNumber, client); await this.ReplaceClaimAsync(user, MFAService.SMS_ID_CLAIM, id); break; @@ -174,7 +174,7 @@ namespace Streetwriters.Identity.Services { var id = this.GetClaimValue(user, MFAService.SMS_ID_CLAIM); if (string.IsNullOrEmpty(id)) throw new Exception("Could not find associated SMS verify id. Please try sending the code again."); - if (SMSSender.VerifyOTP(id, code)) + if (await SMSSender.VerifyOTPAsync(id, code)) { // Auto confirm user phone number if not confirmed if (!await UserManager.IsPhoneNumberConfirmedAsync(user)) diff --git a/Streetwriters.Identity/Services/SMSSender.cs b/Streetwriters.Identity/Services/SMSSender.cs index 3774abf..13515f1 100644 --- a/Streetwriters.Identity/Services/SMSSender.cs +++ b/Streetwriters.Identity/Services/SMSSender.cs @@ -24,6 +24,10 @@ using MessageBird.Objects; using Microsoft.Extensions.Options; using Streetwriters.Identity.Models; using Streetwriters.Common; +using Twilio.Rest.Verify.V2.Service; +using Twilio; +using System.Threading.Tasks; +using System; namespace Streetwriters.Identity.Services { @@ -34,28 +38,39 @@ namespace Streetwriters.Identity.Services { if (!string.IsNullOrEmpty(Constants.MESSAGEBIRD_ACCESS_KEY)) client = Client.CreateDefault(Constants.MESSAGEBIRD_ACCESS_KEY); + + + if (!string.IsNullOrEmpty(Constants.TWILIO_ACCOUNT_SID) && !string.IsNullOrEmpty(Constants.TWILIO_AUTH_TOKEN)) + { + TwilioClient.Init(Constants.TWILIO_ACCOUNT_SID, Constants.TWILIO_AUTH_TOKEN); + } } - public string SendOTP(string number, IClient app) + public async Task SendOTPAsync(string number, IClient app) { - VerifyOptionalArguments optionalArguments = new VerifyOptionalArguments + try { - Originator = app.Name, - Reference = app.Name, - Type = MessageType.Sms, - Template = $"Your {app.Name} 2FA code is: %token. Valid for 5 minutes.", - TokenLength = 6, - Timeout = 60 * 5 - }; - Verify verify = client.CreateVerify(number, optionalArguments); - if (verify.Status == VerifyStatus.Sent) return verify.Id; + var verification = await VerificationResource.CreateAsync( + to: number, + channel: "sms", + pathServiceSid: Constants.TWILIO_SERVICE_SID + ); + return verification.Sid; + } + catch (Exception ex) + { + + } return null; } - public bool VerifyOTP(string id, string code) + public async Task VerifyOTPAsync(string id, string code) { - Verify verify = client.SendVerifyToken(id, code); - return verify.Status == VerifyStatus.Verified; + return (await VerificationCheckResource.CreateAsync( + verificationSid: id, + pathServiceSid: Constants.TWILIO_SERVICE_SID, + code: code + )).Status == "approved"; } } } \ No newline at end of file diff --git a/Streetwriters.Identity/Streetwriters.Identity.csproj b/Streetwriters.Identity/Streetwriters.Identity.csproj index b9a46c0..bc7fc61 100644 --- a/Streetwriters.Identity/Streetwriters.Identity.csproj +++ b/Streetwriters.Identity/Streetwriters.Identity.csproj @@ -33,6 +33,7 @@ +