Skip to content

Commit 4a4f795

Browse files
authored
feat(templates): apply WebOTP pattern to short messages in Boilerplate #9612 (#9613)
1 parent 7bf448e commit 4a4f795

File tree

11 files changed

+66
-49
lines changed

11 files changed

+66
-49
lines changed

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Settings/ChangeEmailSection.razor

+8-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<BitStack FillContent>
1111
@if (Email is not null)
1212
{
13-
<BitTextField ReadOnly Value="@Email" />
13+
<BitTextField Value="@Email" ReadOnly NoValidate />
1414
}
1515

1616
<BitTextField @bind-Value="sendModel.Email"
@@ -54,10 +54,13 @@
5454
Placeholder="@Localizer[nameof(AppStrings.EmailPlaceholder)]" />
5555
<ValidationMessage For="@(() => changeModel.Email)" />
5656

57-
<BitTextField @bind-Value="changeModel.Token"
58-
Type="BitInputType.Number"
59-
Label="@Localizer[nameof(AppStrings.EmailToken)]"
60-
Placeholder="@Localizer[nameof(AppStrings.EmailTokenPlaceholder)]" />
57+
<BitOtpInput @bind-Value="changeModel.Token"
58+
AutoFocus
59+
Length="6"
60+
Size="BitSize.Large"
61+
Type="BitInputType.Number"
62+
OnFill="WrapHandled(ChangeEmail)"
63+
Label="@Localizer[nameof(AppStrings.EmailToken)]" />
6164
<ValidationMessage For="@(() => changeModel.Token)" />
6265

6366
<BitButton IsLoading="isWaiting" ButtonType="BitButtonType.Submit">

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Authorized/Settings/ChangePhoneNumberSection.razor

+8-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<BitStack FillContent>
1111
@if (PhoneNumber is not null)
1212
{
13-
<BitTextField ReadOnly Value="@PhoneNumber" />
13+
<BitTextField Value="@PhoneNumber" ReadOnly NoValidate />
1414
}
1515

1616
<BitTextField @bind-Value="sendModel.PhoneNumber"
@@ -54,10 +54,13 @@
5454
Placeholder="@Localizer[nameof(AppStrings.PhoneNumberPlaceholder)]" />
5555
<ValidationMessage For="@(() => changeModel.PhoneNumber)" />
5656

57-
<BitTextField @bind-Value="changeModel.Token"
58-
Type="BitInputType.Number"
59-
Label="@Localizer[nameof(AppStrings.PhoneToken)]"
60-
Placeholder="@Localizer[nameof(AppStrings.PhoneTokenPlaceholder)]" />
57+
<BitOtpInput @bind-Value="changeModel.Token"
58+
AutoFocus
59+
Length="6"
60+
Size="BitSize.Large"
61+
Type="BitInputType.Number"
62+
OnFill="WrapHandled(ChangePhoneNumber)"
63+
Label="@Localizer[nameof(AppStrings.PhoneToken)]" />
6164
<ValidationMessage For="@(() => changeModel.Token)" />
6265

6366
<BitButton IsLoading="isWaiting" ButtonType="BitButtonType.Submit">

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Web/wwwroot/.well-known/assetlinks.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
[
1+
[
22
{
33
"relation": [
4-
"delegate_permission/common.handle_all_urls"
4+
"delegate_permission/common.handle_all_urls",
5+
"delegate_permission/common.get_login_creds"
56
],
67
"target": {
78
"namespace": "android_app",

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/IdentityController.PhoneConfirmation.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ private async Task SendConfirmPhoneToken(User user, CancellationToken cancellati
7878
var phoneNumber = user.PhoneNumber!;
7979
var token = await userManager.GenerateUserTokenAsync(user, TokenOptions.DefaultPhoneProvider, FormattableString.Invariant($"VerifyPhoneNumber:{phoneNumber},{user.PhoneNumberTokenRequestedOn?.ToUniversalTime()}"));
8080

81-
await phoneService.SendSms(Localizer[nameof(AppStrings.ConfirmPhoneTokenSmsText), token], phoneNumber, cancellationToken);
81+
var message = Localizer[nameof(AppStrings.ConfirmPhoneTokenShortText), token];
82+
var smsMessage = $"{message}{Environment.NewLine}@{HttpContext.Request.GetWebAppUrl().Host} #{token}" /* Web OTP */;
83+
await phoneService.SendSms(smsMessage, phoneNumber, cancellationToken);
8284
}
8385
}

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/IdentityController.ResetPassword.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ public async Task SendResetPasswordToken(SendResetPasswordTokenRequestDto reques
4949

5050
if (await userManager.IsPhoneNumberConfirmedAsync(user))
5151
{
52-
sendMessagesTasks.Add(phoneService.SendSms(message, user.PhoneNumber!, cancellationToken));
52+
var smsMessage = $"{message}{Environment.NewLine}@{HttpContext.Request.GetWebAppUrl().Host} #{token}" /* Web OTP */;
53+
sendMessagesTasks.Add(phoneService.SendSms(smsMessage, user.PhoneNumber!, cancellationToken));
5354
}
5455

5556
//#if (signalR == true)

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/IdentityController.cs

+5-2
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,9 @@ public async Task SendOtp(IdentityRequestDto request, string? returnUrl = null,
308308

309309
if (await userManager.IsPhoneNumberConfirmedAsync(user))
310310
{
311-
var smsMessage = Localizer[nameof(AppStrings.OtpShortText), await userManager.GenerateUserTokenAsync(user, TokenOptions.DefaultPhoneProvider, FormattableString.Invariant($"Otp_Sms,{user.OtpRequestedOn?.ToUniversalTime()}"))].ToString();
311+
var token = await userManager.GenerateUserTokenAsync(user, TokenOptions.DefaultPhoneProvider, FormattableString.Invariant($"Otp_Sms,{user.OtpRequestedOn?.ToUniversalTime()}"));
312+
var message = Localizer[nameof(AppStrings.OtpShortText), token].ToString();
313+
var smsMessage = $"{message}{Environment.NewLine}@{HttpContext.Request.GetWebAppUrl().Host} #{token}" /* Web OTP */;
312314
sendMessagesTasks.Add(phoneService.SendSms(smsMessage, user.PhoneNumber!, cancellationToken));
313315
}
314316

@@ -368,7 +370,8 @@ public async Task SendTwoFactorToken(SignInRequestDto request, CancellationToken
368370

369371
if (firstStepAuthenticationMethod != "Sms" && await userManager.IsPhoneNumberConfirmedAsync(user))
370372
{
371-
sendMessagesTasks.Add(phoneService.SendSms(message, user.PhoneNumber!, cancellationToken));
373+
var smsMessage = $"{message}{Environment.NewLine}@{HttpContext.Request.GetWebAppUrl().Host} #{token}" /* Web OTP */;
374+
sendMessagesTasks.Add(phoneService.SendSms(smsMessage, user.PhoneNumber!, cancellationToken));
372375
}
373376

374377
if (firstStepAuthenticationMethod != "Push")

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Controllers/Identity/UserController.cs

+9-5
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,10 @@ public async Task SendChangePhoneNumberToken(SendPhoneTokenRequestDto request, C
228228

229229
var token = await userManager.GenerateChangePhoneNumberTokenAsync(user!, request.PhoneNumber!);
230230

231-
await phoneService.SendSms(Localizer[nameof(AppStrings.ChangePhoneNumberTokenSmsText), token], request.PhoneNumber!, cancellationToken);
231+
var message = Localizer[nameof(AppStrings.ChangePhoneNumberTokenShortText), token];
232+
var smsMessage = $"{message}{Environment.NewLine}@{HttpContext.Request.GetWebAppUrl().Host} #{token}" /* Web OTP */;
233+
234+
await phoneService.SendSms(smsMessage, request.PhoneNumber!, cancellationToken);
232235
}
233236

234237
[HttpPost]
@@ -388,7 +391,7 @@ public async Task SendElevatedAccessToken(CancellationToken cancellationToken)
388391

389392
List<Task> sendMessagesTasks = [];
390393

391-
var messageText = Localizer[nameof(AppStrings.ElevatedAccessToken), token].ToString();
394+
var message = Localizer[nameof(AppStrings.ElevatedAccessTokenShortText), token].ToString();
392395

393396
if (await userManager.IsEmailConfirmedAsync(user))
394397
{
@@ -397,7 +400,8 @@ public async Task SendElevatedAccessToken(CancellationToken cancellationToken)
397400

398401
if (await userManager.IsPhoneNumberConfirmedAsync(user))
399402
{
400-
sendMessagesTasks.Add(phoneService.SendSms(messageText, user.PhoneNumber!, cancellationToken));
403+
var smsMessage = $"{message}{Environment.NewLine}@{HttpContext.Request.GetWebAppUrl().Host} #{token}" /* Web OTP */;
404+
sendMessagesTasks.Add(phoneService.SendSms(smsMessage, user.PhoneNumber!, cancellationToken));
401405
}
402406

403407
//#if (signalR == true)
@@ -406,11 +410,11 @@ public async Task SendElevatedAccessToken(CancellationToken cancellationToken)
406410
.Where(us => us.UserId == user.Id && us.Id != currentUserSessionId && us.SignalRConnectionId != null)
407411
.Select(us => us.SignalRConnectionId!)
408412
.ToArrayAsync(cancellationToken);
409-
sendMessagesTasks.Add(appHubContext.Clients.Clients(userSessionIdsExceptCurrentUserSessionId).SendAsync(SignalREvents.SHOW_MESSAGE, messageText, cancellationToken));
413+
sendMessagesTasks.Add(appHubContext.Clients.Clients(userSessionIdsExceptCurrentUserSessionId).SendAsync(SignalREvents.SHOW_MESSAGE, message, cancellationToken));
410414
//#endif
411415

412416
//#if (notification == true)
413-
sendMessagesTasks.Add(pushNotificationService.RequestPush(message: messageText, userRelatedPush: true, customSubscriptionFilter: us => us.UserSession!.UserId == user.Id && us.UserSessionId != currentUserSessionId, cancellationToken: cancellationToken));
417+
sendMessagesTasks.Add(pushNotificationService.RequestPush(message: message, userRelatedPush: true, customSubscriptionFilter: us => us.UserSession!.UserId == user.Id && us.UserSessionId != currentUserSessionId, cancellationToken: cancellationToken));
414418
//#endif
415419

416420
await Task.WhenAll(sendMessagesTasks);

src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.fa.resx

+9-9
Original file line numberDiff line numberDiff line change
@@ -933,8 +933,8 @@
933933
<data name="EnterElevatedAccessToken" xml:space="preserve">
934934
<value>لطفا کد ۶ رقمی که ارسال کردیم یا کد Authenticator app خود را وارد کنید</value>
935935
</data>
936-
<data name="ElevatedAccessToken" xml:space="preserve">
937-
<value>توکن {0}</value>
936+
<data name="ElevatedAccessTokenShortText" xml:space="preserve">
937+
<value>{0} کد شماست در Boilerplate</value>
938938
</data>
939939
<data name="WaitForEmailTokenRequestResendDelay" xml:space="preserve">
940940
<value>شما قبلا ایمیل تایید را درخواست کرده اید. دوباره امتحان کنید در {0}</value>
@@ -987,20 +987,20 @@
987987
<data name="WaitForTwoFactorTokenRequestResendDelay" xml:space="preserve">
988988
<value>شما قبلا درخواست ایمیل توکن 2FA را دارید. دوباره امتحان کنید در {0}</value>
989989
</data>
990-
<data name="ChangePhoneNumberTokenSmsText" xml:space="preserve">
991-
<value>{0} توکن تغییر شماره تلفن شما است در Boilerplate.</value>
990+
<data name="ChangePhoneNumberTokenShortText" xml:space="preserve">
991+
<value>{0} کد شماست در Boilerplate</value>
992992
</data>
993-
<data name="ConfirmPhoneTokenSmsText" xml:space="preserve">
994-
<value>{0} توکن تایید شماره تلفن شما است در Boilerplate.</value>
993+
<data name="ConfirmPhoneTokenShortText" xml:space="preserve">
994+
<value>{0} کد شماست در Boilerplate</value>
995995
</data>
996996
<data name="TwoFactorTokenShortText" xml:space="preserve">
997-
<value>{0} توکن احراز هویت مرحله دو شما است در Boilerplate.</value>
997+
<value>{0} کد شماست در Boilerplate</value>
998998
</data>
999999
<data name="OtpShortText" xml:space="preserve">
1000-
<value>{0} پسورد یک‌بار مصرف شما است در Boilerplate.</value>
1000+
<value>{0} کد شماست در Boilerplate</value>
10011001
</data>
10021002
<data name="ResetPasswordTokenShortText" xml:space="preserve">
1003-
<value>{0} توکن تغییر رمز عبور شما است در Boilerplate.</value>
1003+
<value>{0} کد شماست در Boilerplate</value>
10041004
</data>
10051005
<data name="Online" xml:space="preserve">
10061006
<value>آنلاین</value>

src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.nl.resx

+9-9
Original file line numberDiff line numberDiff line change
@@ -933,8 +933,8 @@
933933
<data name="EnterElevatedAccessToken" xml:space="preserve">
934934
<value>Voer de verhoogde toegangstoken in die we u zojuist hebben gestuurd of de code van uw authenticator-app om door te gaan.</value>
935935
</data>
936-
<data name="ElevatedAccessToken" xml:space="preserve">
937-
<value>Token {0}</value>
936+
<data name="ElevatedAccessTokenShortText" xml:space="preserve">
937+
<value>{0} is je code in Boilerplate.</value>
938938
</data>
939939
<data name="WaitForEmailTokenRequestResendDelay" xml:space="preserve">
940940
<value>Je hebt de bevestigingsmail al aangevraagd. Probeer het opnieuw in {0}</value>
@@ -987,20 +987,20 @@
987987
<data name="WaitForTwoFactorTokenRequestResendDelay" xml:space="preserve">
988988
<value>Je hebt de e-mail met de 2FA-token al aangevraagd. Probeer het opnieuw in {0}.</value>
989989
</data>
990-
<data name="ChangePhoneNumberTokenSmsText" xml:space="preserve">
991-
<value>{0} is het token voor het wijzigen van uw telefoonnummer in Boilerplate.</value>
990+
<data name="ChangePhoneNumberTokenShortText" xml:space="preserve">
991+
<value>{0} is je code in Boilerplate.</value>
992992
</data>
993-
<data name="ConfirmPhoneTokenSmsText" xml:space="preserve">
994-
<value>{0} is uw bevestigingstelefoonnummer token in Boilerplate.</value>
993+
<data name="ConfirmPhoneTokenShortText" xml:space="preserve">
994+
<value>{0} is je code in Boilerplate.</value>
995995
</data>
996996
<data name="TwoFactorTokenShortText" xml:space="preserve">
997-
<value>{0} is je tweefactortoken in Boilerplate.</value>
997+
<value>{0} is je code in Boilerplate.</value>
998998
</data>
999999
<data name="OtpShortText" xml:space="preserve">
1000-
<value>{0} is uw OTP in Boilerplate.</value>
1000+
<value>{0} is je code in Boilerplate.</value>
10011001
</data>
10021002
<data name="ResetPasswordTokenShortText" xml:space="preserve">
1003-
<value>{0} is het token voor het opnieuw instellen van uw wachtwoord in Boilerplate.</value>
1003+
<value>{0} is je code in Boilerplate.</value>
10041004
</data>
10051005
<data name="Online" xml:space="preserve">
10061006
<value>Online</value>

src/Templates/Boilerplate/Bit.Boilerplate/src/Shared/Resources/AppStrings.resx

+9-9
Original file line numberDiff line numberDiff line change
@@ -933,8 +933,8 @@
933933
<data name="EnterElevatedAccessToken" xml:space="preserve">
934934
<value>Please enter the elevated access token we just sent you or your authenticator app code to continue.</value>
935935
</data>
936-
<data name="ElevatedAccessToken" xml:space="preserve">
937-
<value>Token {0}</value>
936+
<data name="ElevatedAccessTokenShortText" xml:space="preserve">
937+
<value>{0} is your code in Boilerplate.</value>
938938
</data>
939939
<data name="WaitForEmailTokenRequestResendDelay" xml:space="preserve">
940940
<value>You have already requested the confirmation email. Try again in {0}</value>
@@ -987,20 +987,20 @@
987987
<data name="WaitForTwoFactorTokenRequestResendDelay" xml:space="preserve">
988988
<value>You have already requested the 2FA token email. Try again in {0}.</value>
989989
</data>
990-
<data name="ChangePhoneNumberTokenSmsText" xml:space="preserve">
991-
<value>{0} is your change phone number token in Boilerplate.</value>
990+
<data name="ChangePhoneNumberTokenShortText" xml:space="preserve">
991+
<value>{0} is your code in Boilerplate.</value>
992992
</data>
993-
<data name="ConfirmPhoneTokenSmsText" xml:space="preserve">
994-
<value>{0} is your confirm phone number token in Boilerplate.</value>
993+
<data name="ConfirmPhoneTokenShortText" xml:space="preserve">
994+
<value>{0} is your code in Boilerplate.</value>
995995
</data>
996996
<data name="TwoFactorTokenShortText" xml:space="preserve">
997-
<value>{0} is your two factor token in Boilerplate.</value>
997+
<value>{0} is your code in Boilerplate.</value>
998998
</data>
999999
<data name="OtpShortText" xml:space="preserve">
1000-
<value>{0} is your OTP in Boilerplate.</value>
1000+
<value>{0} is your code in Boilerplate.</value>
10011001
</data>
10021002
<data name="ResetPasswordTokenShortText" xml:space="preserve">
1003-
<value>{0} is your reset password token in Boilerplate.</value>
1003+
<value>{0} is your code in Boilerplate.</value>
10041004
</data>
10051005
<data name="Online" xml:space="preserve">
10061006
<value>Online</value>

src/Templates/Boilerplate/Bit.Boilerplate/src/Tests/PageTests/PageModels/Identity/SettingsPage.Account.Phone.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public async Task AssertTooManyRequestsForChangePhone()
5959

6060
public string GetPhoneToken()
6161
{
62-
var pattern = AppStrings.ChangePhoneNumberTokenSmsText.Replace("{0}", @"\b\d{6}\b");
62+
var pattern = AppStrings.ChangePhoneNumberTokenShortText.Replace("{0}", @"\b\d{6}\b");
6363
return FakePhoneService.GetLastOtpFor(newPhone, pattern);
6464
}
6565

0 commit comments

Comments
 (0)