mirror of
https://github.com/OPSnet/Gazelle.git
synced 2026-01-16 18:04:34 -05:00
clean up MFA code
This commit is contained in:
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
/** @phpstan-var \Gazelle\User $Viewer */
|
||||
/** @phpstan-var \Twig\Environment $Twig */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Gazelle;
|
||||
|
||||
$user = new Manager\User()->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,
|
||||
]);
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
/** @phpstan-var \Gazelle\User $user */
|
||||
/** @phpstan-var \Gazelle\User $Viewer */
|
||||
/** @phpstan-var \Twig\Environment $Twig */
|
||||
|
||||
@@ -6,27 +7,39 @@ declare(strict_types=1);
|
||||
|
||||
namespace Gazelle;
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start(['read_and_close' => 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,
|
||||
]);
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
/** @phpstan-var \Twig\Environment $Twig */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Gazelle;
|
||||
|
||||
echo $Twig->render('user/mfa/remove.twig', [
|
||||
'bad' => isset($_GET['invalid']),
|
||||
]);
|
||||
@@ -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(),
|
||||
};
|
||||
|
||||
@@ -1,27 +1,30 @@
|
||||
<?php
|
||||
/** @phpstan-var \Gazelle\User $user */
|
||||
/** @phpstan-var \Gazelle\User $Viewer */
|
||||
/** @phpstan-var \Twig\Environment $Twig */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Gazelle;
|
||||
|
||||
// Remove MFA. Users have to enter their password, moderators skip this step.
|
||||
$user = new Manager\User()->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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<td class="label">Two-factor Authentication:</td>
|
||||
<td>
|
||||
{% if user.MFA.enabled %}
|
||||
<a href="user.php?action=mfa&page=user&do=remove&userid={{ user.id }}">Click here to remove</a>
|
||||
<a href="user.php?action=mfa&do=remove&userid={{ user.id }}&auth={{ viewer.auth }}">Click here to remove</a>
|
||||
{% else %}
|
||||
Currently inactive
|
||||
{% endif %}
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
</table>
|
||||
|
||||
@@ -6,17 +6,17 @@
|
||||
|
||||
<p>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 <a href="https://itunes.apple.com/gb/app/authy/id494168017?mt=8">App
|
||||
in the Secret Text below it. We recommend using the 2FAS app which
|
||||
you can find in the <a href="https://apps.apple.com/gb/app/2fa-authenticator-2fas/id1217793794">Apple App
|
||||
Store</a> or
|
||||
<a href="https://play.google.com/store/apps/details?id=com.authy.authy&hl=en_GB">Play
|
||||
Store</a>. Other authenticator apps will work too.</p>
|
||||
<a href="https://play.google.com/store/apps/details?id=com.twofasapp">Google Play
|
||||
Store</a>. Other authenticator apps that support TOTP will work too.</p>
|
||||
</div>
|
||||
|
||||
<div class="box box2">
|
||||
<div class="center pad">
|
||||
<div>
|
||||
<img src="{{ qrcode.getDataUri }}">
|
||||
<img alt="MFA QR code" src="{{ qrcode.getDataUri }}">
|
||||
<div class="mfa_text">Secret Text: <span>{{ secret }}</span></div>
|
||||
{% if not valid %}
|
||||
<p class="warning">Please ensure you have imported the correct secret key
|
||||
@@ -37,5 +37,6 @@
|
||||
<label for="mfa"><strong>Authentication Key</strong></label>
|
||||
<input type="text" size="8" name="mfa" id="mfa"/>
|
||||
<input type="submit" value="Authenticate!">
|
||||
</form>
|
||||
</div>
|
||||
{{ footer() }}
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
{% set has_mfa = user.MFA.enabled %}
|
||||
Multi Factor authentication is currently <strong class="{{ has_mfa ? 'r99' : 'warning' }}">{{ has_mfa ? 'enabled' : 'disabled' }}</strong> for your account.
|
||||
<br><br>
|
||||
<a href="user.php?action=mfa&do={{ has_mfa ? 'remove' : 'configure' }}&userid={{ user.id }}">Click here to {{ has_mfa ? 'remove' : 'configure' }}</a>
|
||||
<a href="user.php?action=mfa&do={{ has_mfa ? 'remove' : 'configure' }}&userid={{ user.id }}&auth={{ viewer.auth }}">Click here to {{ has_mfa ? 'remove' : 'configure' }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user