mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-20 13:34:37 +01:00
Fix 2FA config screens
This commit is contained in:
parent
b728cd61ae
commit
006ebf3f15
10 changed files with 119 additions and 76 deletions
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Models;
|
||||
using BTCPayServer.Models.ManageViewModels;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
@ -26,7 +27,6 @@ namespace BTCPayServer.Controllers
|
|||
|
||||
var model = new TwoFactorAuthenticationViewModel
|
||||
{
|
||||
HasAuthenticator = await _userManager.GetAuthenticatorKeyAsync(user) != null,
|
||||
Is2faEnabled = user.TwoFactorEnabled,
|
||||
RecoveryCodesLeft = await _userManager.CountRecoveryCodesAsync(user),
|
||||
};
|
||||
|
@ -49,11 +49,19 @@ namespace BTCPayServer.Controllers
|
|||
$"Unexpected error occurred disabling 2FA for user with ID '{user.Id}'.");
|
||||
}
|
||||
|
||||
return View(nameof(Disable2fa));
|
||||
return View("Confirm",
|
||||
new ConfirmModel()
|
||||
{
|
||||
Title = $"Disable two-factor authentication (2FA)",
|
||||
DescriptionHtml = true,
|
||||
Description =
|
||||
$"Disabling 2FA does not change the keys used in authenticator apps. If you wish to change the key used in an authenticator app you should <a href=\"{Url.Action(nameof(ResetAuthenticatorWarning))}\"> reset your authenticator keys</a>.",
|
||||
Action = "Disable 2FA",
|
||||
ActionUrl = Url.ActionLink(nameof(Disable2fa))
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Disable2fa()
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
|
@ -105,7 +113,8 @@ namespace BTCPayServer.Controllers
|
|||
}
|
||||
|
||||
// Strip spaces and hypens
|
||||
var verificationCode = model.Code.Replace(" ", string.Empty, StringComparison.OrdinalIgnoreCase).Replace("-", string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
var verificationCode = model.Code.Replace(" ", string.Empty, StringComparison.OrdinalIgnoreCase)
|
||||
.Replace("-", string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
var is2faTokenValid = await _userManager.VerifyTwoFactorTokenAsync(
|
||||
user, _userManager.Options.Tokens.AuthenticatorTokenProvider, verificationCode);
|
||||
|
@ -122,17 +131,24 @@ namespace BTCPayServer.Controllers
|
|||
var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10);
|
||||
TempData[RecoveryCodesKey] = recoveryCodes.ToArray();
|
||||
|
||||
return RedirectToAction(nameof(GenerateRecoveryCodes));
|
||||
return RedirectToAction(nameof(GenerateRecoveryCodes), new {confirm = false});
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult ResetAuthenticatorWarning()
|
||||
{
|
||||
return View(nameof(ResetAuthenticator));
|
||||
return View("Confirm",
|
||||
new ConfirmModel()
|
||||
{
|
||||
Title = $"Reset authenticator key",
|
||||
Description =
|
||||
$"This process disables 2FA until you verify your authenticator app and will also reset your 2FA recovery codes.{Environment.NewLine}If you do not complete your authenticator app configuration you may lose access to your account.",
|
||||
Action = "Reset",
|
||||
ActionUrl = Url.ActionLink(nameof(ResetAuthenticator))
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> ResetAuthenticator()
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
|
@ -149,15 +165,39 @@ namespace BTCPayServer.Controllers
|
|||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult GenerateRecoveryCodes()
|
||||
public async Task<IActionResult> GenerateRecoveryCodes(bool confirm = true)
|
||||
{
|
||||
if (!confirm)
|
||||
{
|
||||
return await GenerateRecoveryCodes();
|
||||
}
|
||||
|
||||
return View("Confirm",
|
||||
new ConfirmModel()
|
||||
{
|
||||
Title = $"Are you sure you want to generate new recovery codes?",
|
||||
Description = "Your existing recovery codes will no longer be valid!",
|
||||
Action = "Generate",
|
||||
ActionUrl = Url.ActionLink(nameof(GenerateRecoveryCodes))
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> GenerateRecoveryCodes()
|
||||
{
|
||||
var recoveryCodes = (string[])TempData[RecoveryCodesKey];
|
||||
if (recoveryCodes == null)
|
||||
{
|
||||
return RedirectToAction(nameof(TwoFactorAuthentication));
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
if (user == null)
|
||||
{
|
||||
throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
||||
}
|
||||
|
||||
recoveryCodes = (await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10)).ToArray();
|
||||
}
|
||||
|
||||
var model = new GenerateRecoveryCodesViewModel { RecoveryCodes = recoveryCodes };
|
||||
var model = new GenerateRecoveryCodesViewModel {RecoveryCodes = recoveryCodes};
|
||||
return View(model);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@ namespace BTCPayServer.Models
|
|||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public bool DescriptionHtml { get; set; } = false;
|
||||
|
||||
public string Action
|
||||
{
|
||||
get; set;
|
||||
|
|
|
@ -2,7 +2,6 @@ namespace BTCPayServer.Models.ManageViewModels
|
|||
{
|
||||
public class TwoFactorAuthenticationViewModel
|
||||
{
|
||||
public bool HasAuthenticator { get; set; }
|
||||
|
||||
public int RecoveryCodesLeft { get; set; }
|
||||
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
@{
|
||||
ViewData.SetActivePageAndTitle(ManageNavPages.TwoFactorAuthentication, "Disable two-factor authentication (2FA)");
|
||||
}
|
||||
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<h4 class="alert-heading mb-3">
|
||||
<span class="fa fa-warning"></span>
|
||||
This action only disables 2FA.
|
||||
</h4>
|
||||
<p class="mb-0">
|
||||
Disabling 2FA does not change the keys used in authenticator apps.
|
||||
If you wish to change the key used in an authenticator app you should
|
||||
<a asp-action="ResetAuthenticatorWarning" class="alert-link">
|
||||
reset your authenticator keys.
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<form asp-action="Disable2fa" method="post" class="form-group">
|
||||
<button class="btn btn-danger" type="submit">Disable 2FA</button>
|
||||
</form>
|
||||
</div>
|
|
@ -22,6 +22,6 @@
|
|||
</div>
|
||||
<div class="row mt-4">
|
||||
<div class="col-md-12">
|
||||
<a asp-action="Index" class="btn btn-primary">I wrote down my recovery codes</a>
|
||||
<a asp-action="TwoFactorAuthentication" class="btn btn-primary">I wrote down my recovery codes</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
@{
|
||||
ViewData.SetActivePageAndTitle(ManageNavPages.TwoFactorAuthentication, "Reset authenticator key");
|
||||
}
|
||||
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<h4 class="alert-heading mb-3">
|
||||
<span class="fa fa-warning"></span>
|
||||
Your authenticator app will not work until you reconfigure it.
|
||||
</h4>
|
||||
<p class="mb-2">
|
||||
This process disables 2FA until you verify your authenticator app and will also reset your 2FA recovery codes.
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
If you do not complete your authenticator app configuration you may lose access to your account.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<form asp-action="ResetAuthenticator" method="post" class="form-group">
|
||||
<button class="btn btn-danger" type="submit">Reset authenticator key</button>
|
||||
</form>
|
||||
</div>
|
|
@ -20,7 +20,7 @@
|
|||
<div class="alert alert-danger">
|
||||
<h4 class="alert-heading mb-3">
|
||||
<span class="fa fa-warning"></span>
|
||||
You have 1 recovery code left.
|
||||
You only have 1 recovery code left.
|
||||
</h4>
|
||||
<p class="mb-0">You can <a asp-action="GenerateRecoveryCodes" class="alert-link">generate a new set of recovery codes</a>.</p>
|
||||
</div>
|
||||
|
@ -30,31 +30,60 @@
|
|||
<div class="alert alert-warning">
|
||||
<h4 class="alert-heading mb-3">
|
||||
<span class="fa fa-warning"></span>
|
||||
You have @Model.RecoveryCodesLeft recovery codes left.
|
||||
You only have @Model.RecoveryCodesLeft recovery codes left.
|
||||
</h4>
|
||||
<p class="mb-0">You should <a asp-action="GenerateRecoveryCodes" class="alert-link">generate a new set of recovery codes</a>.</p>
|
||||
</div>
|
||||
}
|
||||
<h5>Your current 2FA</h5>
|
||||
<ul>
|
||||
<li><a asp-action="Disable2faWarning">Disable 2FA</a></li>
|
||||
<li><a asp-action="GenerateRecoveryCodes">Reset recovery codes</a></li>
|
||||
</ul>
|
||||
}
|
||||
|
||||
<h5 class="mt-4">Authenticator app</h5>
|
||||
<ul>
|
||||
<div class="row">
|
||||
<div class="list-group">
|
||||
|
||||
@if(!Model.HasAuthenticator)
|
||||
{
|
||||
<li><a asp-action="EnableAuthenticator">Add authenticator app</a></li>
|
||||
}
|
||||
else
|
||||
{
|
||||
<li><a asp-action="EnableAuthenticator">Configure authenticator app</a></li>
|
||||
<li><a asp-action="ResetAuthenticatorWarning">Reset authenticator key</a></li>
|
||||
}
|
||||
</ul>
|
||||
@if (Model.Is2faEnabled)
|
||||
{
|
||||
<a asp-action="Disable2faWarning" class="list-group-item d-flex justify-content-between align-items-center list-group-item-action">
|
||||
<div>
|
||||
<h5 >Disable 2FA</h5>
|
||||
<p class="mb-1">Disable two-factor authentication. Re-enabling will not require you to reconfigure your Authenticator app. </p>
|
||||
</div>
|
||||
<i class="fa fa-chevron-right"></i>
|
||||
</a>
|
||||
<a asp-action="GenerateRecoveryCodes" class="list-group-item d-flex justify-content-between align-items-center list-group-item-action">
|
||||
<div>
|
||||
<h5 >Reset recovery codes</h5>
|
||||
<p class="mb-1">Regenerate your two-factor recovery codes.</p>
|
||||
</div>
|
||||
<i class="fa fa-chevron-right"></i>
|
||||
</a>
|
||||
|
||||
<a asp-action="EnableAuthenticator" class="list-group-item d-flex justify-content-between align-items-center list-group-item-action">
|
||||
<div>
|
||||
<h5 >Configure Authenticator app</h5>
|
||||
<p class="mb-1">Display the key or QR code to configure an authenticator app with your current setup.</p>
|
||||
</div>
|
||||
<i class="fa fa-chevron-right"></i>
|
||||
</a>
|
||||
<a asp-action="ResetAuthenticatorWarning" class="list-group-item d-flex justify-content-between align-items-center list-group-item-action">
|
||||
<div>
|
||||
<h5 >Reset Authenticator app</h5>
|
||||
<p class="mb-1">Invalidates the current authenticator configuration. Useful if you believe your authenticator settings were compromised.</p>
|
||||
</div>
|
||||
<i class="fa fa-chevron-right"></i>
|
||||
</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a asp-action="EnableAuthenticator" class="list-group-item d-flex justify-content-between align-items-center list-group-item-action">
|
||||
<div>
|
||||
<h5 >Enable 2FA</h5>
|
||||
<p class="mb-1">Enable two-factor authentication using TOTP with apps such as Google Authenticator.</p>
|
||||
</div>
|
||||
<i class="fa fa-chevron-right"></i>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@await Html.PartialAsync("_ValidationScriptsPartial")
|
||||
|
|
|
@ -19,7 +19,16 @@
|
|||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<p>@Model.Description</p>
|
||||
<p>
|
||||
@if (Model.DescriptionHtml)
|
||||
{
|
||||
@Safe.Raw(Model.Description)
|
||||
}
|
||||
else
|
||||
{
|
||||
@Model.Description
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@if (!String.IsNullOrEmpty(Model.Action))
|
||||
|
|
|
@ -110,3 +110,7 @@ header.masthead::before,
|
|||
.table th {
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.list-group-item-action {
|
||||
color: var(--btcpay-body-color);
|
||||
}
|
||||
|
|
|
@ -42,3 +42,6 @@
|
|||
.table-sm tbody tr:hover {
|
||||
background-color: var(--btcpay-color-neutral-950);
|
||||
}
|
||||
.list-group-item-action {
|
||||
color: var(--btcpay-body-color);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue