diff --git a/sections/user/mfa/complete.php b/sections/user/mfa/complete.php deleted file mode 100644 index 9bbe7f43b..000000000 --- a/sections/user/mfa/complete.php +++ /dev/null @@ -1,37 +0,0 @@ -findById((int)($_REQUEST['userid'] ?? 0)); -if (is_null($user)) { - Error404::error(); -} -if ($user->MFA()->enabled()) { - Error400::error('MFA is already configured'); -} - -if (session_status() === PHP_SESSION_NONE) { - session_start(['read_and_close' => true]); -} -if (empty($_SESSION['private_key'])) { - Error404::error(); -} - -$recoveryKeys = $user->MFA()->create(new Manager\UserToken(), $_SESSION['private_key'], $Viewer); -if (!$recoveryKeys) { - Error400::error('failed to create MFA'); -} - -if (session_status() === PHP_SESSION_NONE) { - session_start(); -} -unset($_SESSION['private_key']); -session_write_close(); - -echo $Twig->render('user/mfa/complete.twig', [ - 'keys' => $recoveryKeys, -]); diff --git a/sections/user/mfa/configure.php b/sections/user/mfa/configure.php index 4ecc3faaa..cf8290ee2 100644 --- a/sections/user/mfa/configure.php +++ b/sections/user/mfa/configure.php @@ -1,4 +1,5 @@ true]); +if (!isset($user)) { + Error500::error(); +} +$mfa = $user->MFA(); +if ($mfa->enabled()) { + Error400::error('MFA is already configured'); +} + +if (session_status() === PHP_SESSION_NONE) { + session_start(); } -$mfa = $Viewer->MFA(); $valid = true; -if (!empty($_SESSION['private_key'])) { +if (isset($_SESSION['private_key'], $_POST['mfa'])) { $secret = $_SESSION['private_key']; - if (isset($_POST['mfa'])) { - if ($mfa->verifyCode($secret, trim($_POST['mfa']))) { - header("Location: user.php?action=mfa&do=complete&userid={$Viewer->id}"); - exit; + if ($mfa->verifyCode($secret, trim($_POST['mfa']))) { + $recoveryKeys = $user->MFA()->create(new Manager\UserToken(), $_SESSION['private_key'], $Viewer); + if (!$recoveryKeys) { + Error400::error('failed to create MFA'); } - $valid = false; + unset($_SESSION['private_key']); + session_write_close(); + + echo $Twig->render('user/mfa/complete.twig', [ + 'keys' => $recoveryKeys, + ]); + exit; } + session_abort(); + $valid = false; } else { - $secret = $mfa->generateSessionSecret(); - if (session_status() === PHP_SESSION_NONE) { - session_start(); - } - $_SESSION['private_key'] = $secret; + authorize(); + $_SESSION['private_key'] = $secret = $mfa->generateSessionSecret(); session_write_close(); } @@ -34,5 +47,4 @@ echo $Twig->render('user/mfa/configure.twig', [ 'valid' => $valid, 'qrcode' => $mfa->generateQrCode(secret: $secret, logo: QRCODE_LOGO), 'secret' => $secret, - 'viewer' => $Viewer, ]); diff --git a/sections/user/mfa/confirm.php b/sections/user/mfa/confirm.php deleted file mode 100644 index bd02e7814..000000000 --- a/sections/user/mfa/confirm.php +++ /dev/null @@ -1,10 +0,0 @@ -render('user/mfa/remove.twig', [ - 'bad' => isset($_GET['invalid']), -]); diff --git a/sections/user/mfa/index.php b/sections/user/mfa/index.php index e0ba38fa6..bc14ecfd1 100644 --- a/sections/user/mfa/index.php +++ b/sections/user/mfa/index.php @@ -7,28 +7,14 @@ namespace Gazelle; $user = new Manager\User()->findById((int)($_REQUEST['userid'] ?? 0)); if (is_null($user)) { - Error404::error(); + Error404::error('No such user'); } if ($user->id != $Viewer->id && !$Viewer->permitted('users_mod')) { Error403::error(); } -switch ($_GET['do'] ?? '') { - case 'configure': - if ($user->MFA()->enabled()) { - Error400::error('MFA is already configured'); - } - include_once __DIR__ . '/configure.php'; - break; - - case 'complete': - include_once __DIR__ . '/complete.php'; - break; - - case 'remove': - include_once __DIR__ . '/remove.php'; - break; - - default: - Error404::error(); -} +require_once __DIR__ . '/' . match ($_GET['do'] ?? '') { + 'configure' => 'configure.php', + 'remove' => 'remove.php', + default => Error404::error(), +}; diff --git a/sections/user/mfa/remove.php b/sections/user/mfa/remove.php index ee8d86109..8d8a7b923 100644 --- a/sections/user/mfa/remove.php +++ b/sections/user/mfa/remove.php @@ -1,27 +1,30 @@ findById((int)($_GET['userid'] ?? 0)); -if (is_null($user)) { - Error404::error(); +if (!isset($user)) { + Error500::error(); } if (!$user->MFA()->enabled()) { Error400::error('No MFA configured'); } -if (!$Viewer->permitted('users_edit_password')) { +// Remove MFA. Users have to enter their password, moderators skip this step. +if ($Viewer->permitted('users_edit_password')) { + authorize(); +} else { if ($user->id !== $Viewer->id) { Error403::error(); - } elseif (empty($_POST['password'])) { - include_once 'confirm.php'; + } elseif (!isset($_POST['password'])) { + echo $Twig->render('user/mfa/remove.twig', ['bad' => false]); exit; } elseif (!$user->validatePassword($_POST['password'])) { - header("Location: user.php?action=mfa&do=remove&invalid=1&userid={$user->id}"); + echo $Twig->render('user/mfa/remove.twig', ['bad' => true]); exit; } } diff --git a/templates/user/edit-password.twig b/templates/user/edit-password.twig index 72302d5b2..e43addbbb 100644 --- a/templates/user/edit-password.twig +++ b/templates/user/edit-password.twig @@ -9,7 +9,7 @@ Two-factor Authentication: {% if user.MFA.enabled %} - Click here to remove + Click here to remove {% else %} Currently inactive {% endif %} diff --git a/templates/user/main-column.twig b/templates/user/main-column.twig index 1f8730948..c06c784f5 100644 --- a/templates/user/main-column.twig +++ b/templates/user/main-column.twig @@ -120,7 +120,7 @@ {% endif %} {% if viewer.permitted('users_edit_password') %} -{% include 'user/edit-password.twig' with {'user': user} only %} +{% include 'user/edit-password.twig' with {'user': user, 'viewer': viewer} only %} {% endif %} diff --git a/templates/user/mfa/configure.twig b/templates/user/mfa/configure.twig index a210de03a..e4c65d215 100644 --- a/templates/user/mfa/configure.twig +++ b/templates/user/mfa/configure.twig @@ -6,17 +6,17 @@

We have generated a secure secret that only we should share. Please import it into your phone, either by scanning the QR key, or copying - in the Secret Text below it. We recommend using the Authy app which - you can find in the App + in the Secret Text below it. We recommend using the 2FAS app which + you can find in the Apple App Store or - Play - Store. Other authenticator apps will work too.

+ Google Play + Store. Other authenticator apps that support TOTP will work too.

- + MFA QR code
Secret Text: {{ secret }}
{% if not valid %}

Please ensure you have imported the correct secret key @@ -37,5 +37,6 @@         +

{{ footer() }} diff --git a/templates/user/setting/access.twig b/templates/user/setting/access.twig index 196abafeb..54b35b71e 100644 --- a/templates/user/setting/access.twig +++ b/templates/user/setting/access.twig @@ -85,7 +85,7 @@ {% set has_mfa = user.MFA.enabled %} Multi Factor authentication is currently {{ has_mfa ? 'enabled' : 'disabled' }} for your account.

- Click here to {{ has_mfa ? 'remove' : 'configure' }} + Click here to {{ has_mfa ? 'remove' : 'configure' }}