Further improve the MFA process, now when verification fails the modal will stay open and the secret remain the same

This commit is contained in:
johnnyq 2025-01-28 16:34:07 -05:00
parent ec9572c2ec
commit 9ea5fdf425
3 changed files with 49 additions and 8 deletions

View File

@ -1,8 +1,12 @@
<?php
require_once 'plugins/totp/totp.php';
//Generate a base32 Key
$token = key32gen();
// Only generate the token once and store it in session:
if (empty($_SESSION['mfa_token'])) {
$token = key32gen();
$_SESSION['mfa_token'] = $token;
}
$token = $_SESSION['mfa_token'];
// Generate QR Code
$data = "otpauth://totp/ITFlow:$session_email?secret=$token";
@ -13,14 +17,13 @@ $data = "otpauth://totp/ITFlow:$session_email?secret=$token";
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-lock mr-2"></i>Enabling Multi-Factor Authentication</h5>
<h5 class="modal-title"><i class="fa fa-fw fa-lock mr-2"></i>Multi-Factor Authentication</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<input type="hidden" name="token" value="<?php echo $token; ?>">
<div class="modal-body bg-white">
<div class="text-center">
@ -35,7 +38,7 @@ $data = "otpauth://totp/ITFlow:$session_email?secret=$token";
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-lock"></i></span>
</div>
<input type="text" class="form-control" inputmode="numeric" pattern="[0-9]*" name="verify_code" placeholder="Enter 6 digit code to verify MFA" required>
<input type="text" class="form-control" inputmode="numeric" pattern="[0-9]*" minlength="6" maxlength="6" name="verify_code" placeholder="Enter 6 digit code to verify MFA" required>
</div>
</div>

View File

@ -214,11 +214,20 @@ if (isset($_POST['enable_mfa'])) {
require_once "plugins/totp/totp.php";
$verify_code = intval($_POST['verify_code']); //code to validate, for example received from device
$token = sanitizeInput($_POST['token']);
// Grab the code from the user
$verify_code = trim($_POST['verify_code']);
// Ensure it's numeric
if (!ctype_digit($verify_code)) {
$verify_code = '';
}
// Grab the secret from the session
$token = $_SESSION['mfa_token'] ?? '';
// Verify
if (TokenAuth6238::verify($token, $verify_code)) {
// SUCCESS
mysqli_query($mysqli,"UPDATE users SET user_token = '$token' WHERE user_id = $session_user_id");
// Delete any existing 2FA tokens - these browsers should be re-validated
@ -229,12 +238,20 @@ if (isset($_POST['enable_mfa'])) {
$_SESSION['alert_message'] = "Multi-Factor authentication enabled";
// Clear the mfa_token from the session to avoid re-use.
unset($_SESSION['mfa_token']);
} else {
// FAILURE
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Verification Code Invalid, Multi-Factor Authenticaion not enabled, Try again!";
$_SESSION['alert_message'] = "Verification code invalid, please try again.";
// Set a flag to automatically open the MFA modal again
$_SESSION['show_mfa_modal'] = true;
}
header("Location: user_security.php");
exit;
}

View File

@ -76,4 +76,25 @@ $remember_token_count = mysqli_num_rows($sql_remember_tokens);
<?php } ?>
<?php
// Show the error alert if it exists:
if (!empty($_SESSION['alert_type']) && $_SESSION['alert_type'] == 'error') {
echo "<div class='alert alert-danger'>{$_SESSION['alert_message']}</div>";
// Clear it so it doesn't persist on refresh
unset($_SESSION['alert_type']);
unset($_SESSION['alert_message']);
}
// If the user just failed a TOTP verification, auto-open the modal:
if (!empty($_SESSION['show_mfa_modal'])) {
echo "
<script>
document.addEventListener('DOMContentLoaded', function() {
// jQuery or vanilla JS to open the modal
$('#enableMFAModal').modal('show');
});
</script>";
unset($_SESSION['show_mfa_modal']);
}
require_once "includes/footer.php";