Skip to content

Commit 7310d53

Browse files
committed
Updates
1 parent 8f12c38 commit 7310d53

File tree

1 file changed

+26
-43
lines changed

1 file changed

+26
-43
lines changed

aspnetcore/blazor/security/webassembly/standalone-with-identity/qrcodes-for-authenticator-apps.md

Lines changed: 26 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ public async Task<TwoFactorResult> TwoFactorRequest(
370370
Replace the `Login` component. The following version of the `Login` component:
371371

372372
* Accepts a user's email address (user ID) and password for an initial login attempt.
373-
* If login is successful (2FA is diabled), the component notifies the user that they're authenticated.
373+
* If login is successful (2FA is disabled), the component notifies the user that they're authenticated.
374374
* If the login attempt results in a response indicating that 2FA is required, a 2FA input element appears to receive either a 2FA TOTP code from an authenticator app or a recovery code. Depending on which code the user enters, login is attempted again by calling either `LoginTwoFactorCodeAsync` for a TOTP code or `LoginTwoFactorRecoveryCodeAsync` for a recovery code.
375375

376376
`Components/Identity/Login.razor`:
@@ -393,6 +393,12 @@ Replace the `Login` component. The following version of the `Login` component:
393393
<div class="alert alert-success">
394394
You're logged in as @context.User.Identity?.Name.
395395
</div>
396+
@if (!string.IsNullOrEmpty(recoveryCodesRemainingMessage))
397+
{
398+
<div class="alert alert-warning">
399+
@recoveryCodesRemainingMessage
400+
</div>
401+
}
396402
</Authorized>
397403
<NotAuthorized>
398404
@foreach (var error in formResult.ErrorList)
@@ -468,6 +474,7 @@ Replace the `Login` component. The following version of the `Login` component:
468474
@code {
469475
private FormResult formResult = new();
470476
private bool requiresTwoFactor;
477+
private string? recoveryCodesRemainingMessage;
471478
472479
[SupplyParameterFromForm]
473480
private InputModel Input { get; set; } = new();
@@ -490,6 +497,12 @@ Replace the `Login` component. The following version of the `Login` component:
490497
{
491498
formResult = await Acct.LoginTwoFactorRecoveryCodeAsync(
492499
Input.Email, Input.Password, Input.TwoFactorCode);
500+
501+
recoveryCodesRemainingMessage =
502+
$"You have {twoFactorResult.RecoveryCodesLeft} recovery " +
503+
"codes remaining.";
504+
505+
StateHasChanged();
493506
}
494507
}
495508
}
@@ -573,34 +586,6 @@ If 2FA isn't enabled, the component loads a form with a QR code to enable 2FA wi
573586

574587
If 2FA is enabled, a button appears to disable 2FA.
575588

576-
<!-- NOTE TO REVIEWERS!
577-
578-
I'm not discussing recovery code generation in this text yet
579-
because I'm not clear on how that's supposed to work because
580-
submitting such a request doesn't just re-gen the recovery
581-
codes ... it also disables 2FA. That might be a bug in the
582-
API, but it's more likely that I don't understand the logic
583-
of recovery code re-gen. I've sent an email to discuss
584-
this point.
585-
586-
What we might be doing for this is simply removing the
587-
recovery code re-gen (including from the cookie auth state
588-
provider code method for `/manage/2fa` management).
589-
Leave it so that the codes are shown once when 2FA is
590-
enabled, and then don't permit re-gen from the app. If the
591-
user hasn't resolved their 2FA/TOTP app login situation
592-
(new phone, new TOTP app, etc.) and they've used all of
593-
their recovery codes, then they're simply locked out until
594-
customer service/IT reactivates their account.
595-
596-
BTW ... The 'forget machine' piece also doesn't seem
597-
particularly relevant. Machines are always remembered by
598-
the current API AFAICT. Perhaps, the only way to require
599-
TOTP every login attempt is to call for forgetting the
600-
machine after every successful login ... not sure ... this
601-
subject will be my follow-up question on the email convo.
602-
-->
603-
604589
`Components/Identity/Manage2fa.razor`:
605590

606591
```razor
@@ -631,7 +616,6 @@ If 2FA is enabled, a button appears to disable 2FA.
631616
{
632617
<div class="alert alert-danger">@error</div>
633618
}
634-
635619
@if (twoFactorResult.IsTwoFactorEnabled)
636620
{
637621
<div class="alert alert-success" role="alert">
@@ -644,7 +628,7 @@ If 2FA is enabled, a button appears to disable 2FA.
644628
</button>
645629
</div>
646630
647-
@if (recoveryCodes is null)
631+
@if (twoFactorResult.RecoveryCodes is null)
648632
{
649633
<div class="m-1">
650634
<button @onclick="GenerateNewCodes"
@@ -656,7 +640,7 @@ If 2FA is enabled, a button appears to disable 2FA.
656640
else
657641
{
658642
<ShowRecoveryCodes
659-
RecoveryCodes="twoFactorResult.RecoveryCodes.ToArray()" />
643+
RecoveryCodes="twoFactorResult.RecoveryCodes" />
660644
}
661645
}
662646
else
@@ -710,10 +694,10 @@ If 2FA is enabled, a button appears to disable 2FA.
710694
<div class="row">
711695
<div class="col-xl-6">
712696
<EditForm
713-
Model="Input"
714-
FormName="send-code"
715-
OnValidSubmit="OnValidSubmitAsync"
716-
method="post">
697+
Model="Input"
698+
FormName="send-code"
699+
OnValidSubmit="OnValidSubmitAsync"
700+
method="post">
717701
<DataAnnotationsValidator />
718702
<div class="form-floating mb-3">
719703
<InputText
@@ -722,8 +706,7 @@ If 2FA is enabled, a button appears to disable 2FA.
722706
class="form-control"
723707
autocomplete="off"
724708
placeholder="Enter the code" />
725-
<label for="Input.Code"
726-
class="control-label form-label">
709+
<label for="Input.Code" class="control-label form-label">
727710
Verification Code
728711
</label>
729712
<ValidationMessage
@@ -781,7 +764,7 @@ If 2FA is enabled, a button appears to disable 2FA.
781764
"otpauth://totp/{0}:{1}?secret={2}&issuer={0}&digits=6",
782765
UrlEncoder.Default.Encode(Config["TotpOrganizationName"]!),
783766
email,
784-
twoFactorResult?.SharedKey);
767+
twoFactorResult.SharedKey);
785768
786769
await module.InvokeVoidAsync("setQrCode", qrCodeElement, uri);
787770
}
@@ -790,20 +773,20 @@ If 2FA is enabled, a button appears to disable 2FA.
790773
private async Task Disable2FA()
791774
{
792775
twoFactorResult =
793-
await Acct.TwoFactorRequest(enable: false, resetSharedKey: true);
776+
await Acct.TwoFactorRequest(resetSharedKey: true);
794777
}
795778
796779
private async Task GenerateNewCodes()
797780
{
798781
twoFactorResult =
799-
await Acct.TwoFactorRequest(enable: false, resetRecoveryCodes: true);
782+
await Acct.TwoFactorRequest(resetRecoveryCodes: true);
800783
}
801784
802785
private async Task OnValidSubmitAsync()
803786
{
804787
twoFactorResult = await Acct.TwoFactorRequest(enable: true,
805788
twoFactorCode: Input.Code);
806-
recoveryCodes = twoFactorResult.RecoveryCodes;
789+
Input.Code = string.Empty;
807790
}
808791
809792
private sealed class InputModel
@@ -832,7 +815,7 @@ Add the following [collocated JavaScript file](xref:blazor/js-interop/javascript
832815

833816
```javascript
834817
export function setQrCode(qrCodeElement, uri) {
835-
if (qrCodeElement !== null) {
818+
if (qrCodeElement !== null && !qrCodeElement.innerHTML.trim()) {
836819
QrCreator.render({
837820
text: uri,
838821
radius: 0,

0 commit comments

Comments
 (0)