mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-05-16 12:29:01 -04:00
85 lines
4.0 KiB
Plaintext
85 lines
4.0 KiB
Plaintext
@page "/user/loginWithRecoveryCode"
|
|
@using AliasVault.Shared.Models.Enums
|
|
|
|
<LayoutPageTitle>Recovery code verification</LayoutPageTitle>
|
|
|
|
<h2 class="text-2xl font-bold text-gray-900 dark:text-white mb-4">
|
|
Recovery code verification
|
|
</h2>
|
|
|
|
<ServerValidationErrors @ref="ServerValidationErrors" />
|
|
|
|
<p class="text-gray-700 dark:text-gray-300 mb-6">
|
|
You have requested to log in with a recovery code. A recovery code is a one-time code that can be used to log in to your account.
|
|
Note that if you don't manually disable 2FA after login, you will be asked for an authenticator code again at the next login.
|
|
</p>
|
|
<div class="w-full max-w-md">
|
|
<EditForm Model="Input" FormName="login-with-recovery-code" OnValidSubmit="OnValidSubmitAsync" method="post" class="space-y-6">
|
|
<DataAnnotationsValidator/>
|
|
<ValidationSummary class="text-red-600 dark:text-red-400" role="alert"/>
|
|
<div>
|
|
<label for="recovery-code" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Recovery Code</label>
|
|
<InputText @bind-Value="Input.RecoveryCode" id="recovery-code" class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" autocomplete="off" placeholder="Enter your recovery code"/>
|
|
<ValidationMessage For="() => Input.RecoveryCode" class="text-red-600 dark:text-red-400 text-sm mt-1"/>
|
|
</div>
|
|
<button type="submit" class="w-full text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800">Log in</button>
|
|
</EditForm>
|
|
</div>
|
|
|
|
@code {
|
|
private AdminUser user = default!;
|
|
|
|
[SupplyParameterFromForm] private InputModel Input { get; set; } = default!;
|
|
|
|
[SupplyParameterFromQuery] private string? ReturnUrl { get; set; }
|
|
|
|
/// <inheritdoc />
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
Input ??= new();
|
|
// Ensure the user has gone through the username & password screen first
|
|
user = await SignInManager.GetTwoFactorAuthenticationUserAsync() ??
|
|
throw new InvalidOperationException("Unable to load two-factor authentication user.");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Submits the form.
|
|
/// </summary>
|
|
private async Task OnValidSubmitAsync()
|
|
{
|
|
ServerValidationErrors.Clear();
|
|
|
|
var recoveryCode = Input.RecoveryCode.Replace(" ", string.Empty);
|
|
var result = await SignInManager.TwoFactorRecoveryCodeSignInAsync(recoveryCode);
|
|
var userId = await UserManager.GetUserIdAsync(user);
|
|
|
|
if (result.Succeeded)
|
|
{
|
|
await AuthLoggingService.LogAuthEventSuccessAsync(user.UserName!, AuthEventType.TwoFactorAuthentication);
|
|
Logger.LogInformation("User with ID '{UserId}' logged in with a recovery code.", userId);
|
|
NavigationService.RedirectTo(ReturnUrl);
|
|
}
|
|
else if (result.IsLockedOut)
|
|
{
|
|
await AuthLoggingService.LogAuthEventFailAsync(user.UserName!, AuthEventType.TwoFactorAuthentication, AuthFailureReason.AccountLocked);
|
|
Logger.LogWarning("User account locked out.");
|
|
NavigationService.RedirectTo("user/lockout");
|
|
}
|
|
else
|
|
{
|
|
await AuthLoggingService.LogAuthEventFailAsync(user.UserName!, AuthEventType.TwoFactorAuthentication, AuthFailureReason.InvalidRecoveryCode);
|
|
Logger.LogWarning("Invalid recovery code entered for user with ID '{UserId}' ", userId);
|
|
ServerValidationErrors.AddError("Error: Invalid recovery code entered.");
|
|
}
|
|
}
|
|
|
|
private sealed class InputModel
|
|
{
|
|
[Required]
|
|
[DataType(DataType.Text)]
|
|
[Display(Name = "Recovery Code")]
|
|
public string RecoveryCode { get; set; } = "";
|
|
}
|
|
|
|
}
|