Files
Aaru.Server/Aaru.Server.New/Components/Account/Pages/LoginWith2fa.razor

101 lines
3.9 KiB
Plaintext

@page "/Account/LoginWith2fa"
@using System.ComponentModel.DataAnnotations
@using Microsoft.AspNetCore.Identity
@using Aaru.Server.New.Data
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager
@inject IdentityRedirectManager RedirectManager
@inject ILogger<LoginWith2fa> Logger
<PageTitle>Two-factor authentication</PageTitle>
<h1>Two-factor authentication</h1>
<hr/>
<StatusMessage Message="@message"/>
<p>Your login is protected with an authenticator app. Enter your authenticator code below.</p>
<div class="row">
<div class="col-md-4">
<EditForm FormName="login-with-2fa" method="post" Model="Input" OnValidSubmit="OnValidSubmitAsync">
<input name="ReturnUrl" type="hidden" value="@ReturnUrl"/>
<input name="RememberMe" type="hidden" value="@RememberMe"/>
<DataAnnotationsValidator/>
<ValidationSummary class="text-danger" role="alert"/>
<div class="form-floating mb-3">
<InputText autocomplete="off" @bind-Value="Input.TwoFactorCode" class="form-control"/>
<label class="form-label" for="two-factor-code">Authenticator code</label>
<ValidationMessage class="text-danger" For="() => Input.TwoFactorCode"/>
</div>
<div class="checkbox mb-3">
<label class="form-label" for="remember-machine">
<InputCheckbox @bind-Value="Input.RememberMachine"/>
Remember this machine
</label>
</div>
<div>
<button class="btn btn-lg btn-primary w-100" type="submit">Log in</button>
</div>
</EditForm>
</div>
</div>
<p>
Don't have access to your authenticator device? You can
<a href="Account/LoginWithRecoveryCode?ReturnUrl=@ReturnUrl">log in with a recovery code</a>.
</p>
@code {
private string? message;
private ApplicationUser user = default!;
[SupplyParameterFromForm]
private InputModel Input { get; set; } = new();
[SupplyParameterFromQuery]
private string? ReturnUrl { get; set; }
[SupplyParameterFromQuery]
private bool RememberMe { get; set; }
protected override async Task OnInitializedAsync()
{
// 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.");
}
private async Task OnValidSubmitAsync()
{
var authenticatorCode = Input.TwoFactorCode!.Replace(" ", string.Empty).Replace("-", string.Empty);
var result = await SignInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, RememberMe, Input.RememberMachine);
var userId = await UserManager.GetUserIdAsync(user);
if(result.Succeeded)
{
Logger.LogInformation("User with ID '{UserId}' logged in with 2fa.", userId);
RedirectManager.RedirectTo(ReturnUrl);
}
else if(result.IsLockedOut)
{
Logger.LogWarning("User with ID '{UserId}' account locked out.", userId);
RedirectManager.RedirectTo("Account/Lockout");
}
else
{
Logger.LogWarning("Invalid authenticator code entered for user with ID '{UserId}'.", userId);
message = "Error: Invalid authenticator code.";
}
}
private sealed class InputModel
{
[Required]
[StringLength(7, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Text)]
[Display(Name = "Authenticator code")]
public string? TwoFactorCode { get; set; }
[Display(Name = "Remember this machine")]
public bool RememberMachine { get; set; }
}
}