Sindbad~EG File Manager
<?php
/**
* Two-Factor Authentication Verification Page (Admin Login)
*/
session_start();
require_once 'config/config.php';
require_once 'classes/TwoFactorAuth.php';
// Check if user is in 2FA verification state
if (!isset($_SESSION['2fa_user_id']) || !isset($_SESSION['2fa_user_type'])) {
header('Location: login.php');
exit;
}
$userId = $_SESSION['2fa_user_id'];
$userType = $_SESSION['2fa_user_type'];
$twoFA = new TwoFactorAuth($userType);
$error = '';
$showBackupForm = false;
$showEmailOTP = false;
$showSMSOTP = false;
// Get 2FA settings
$settings = $twoFA->get2FASettings($userId);
$enabledMethods = $twoFA->getEnabledMethods($userId);
// Determine current method being used
$currentMethod = $_SESSION['2fa_current_method'] ?? $settings['primary_method'] ?? 'totp';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Handle method switching
if (isset($_POST['switch_method'])) {
$currentMethod = $_POST['method'] ?? 'totp';
$_SESSION['2fa_current_method'] = $currentMethod;
// Auto-send OTP if switching to email/SMS
if ($currentMethod === 'email' || $currentMethod === 'sms') {
$twoFA->generateOTP($userId, $currentMethod);
$showEmailOTP = ($currentMethod === 'email');
$showSMSOTP = ($currentMethod === 'sms');
}
}
if (isset($_POST['verify_code'])) {
$code = trim($_POST['code'] ?? '');
$method = $currentMethod;
$verified = false;
if ($method === 'totp') {
$verified = $twoFA->verifyTOTP($settings['totp_secret'], $code);
} elseif ($method === 'email' || $method === 'sms') {
$verified = $twoFA->verifyOTP($userId, $code);
}
if ($verified) {
// Log successful attempt
$twoFA->logAttempt($userId, $method, true);
// Complete login
if ($userType === 'admin') {
$db = Database::getInstance()->getConnection();
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$userId]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $user['username'];
$_SESSION['email'] = $user['email'];
$_SESSION['full_name'] = $user['full_name'];
$_SESSION['access_level'] = $user['access_level'];
$_SESSION['logged_in'] = true;
unset($_SESSION['2fa_user_id']);
unset($_SESSION['2fa_user_type']);
unset($_SESSION['2fa_current_method']);
header('Location: dashboard.php');
exit;
} else {
// Member login - restore account data from session
$account = $_SESSION['2fa_account_data'] ?? null;
if ($account) {
$_SESSION['member_id'] = $account['member_id'];
$_SESSION['member_account_id'] = $account['id'];
$_SESSION['member_username'] = $account['username'];
$_SESSION['member_full_name'] = $account['full_name'];
$_SESSION['member_title'] = $account['title'] ?? '';
} else {
// Fallback: query from database
$db = Database::getInstance()->getConnection();
$stmt = $db->prepare("SELECT * FROM member_accounts WHERE member_id = ?");
$stmt->execute([$userId]);
$account = $stmt->fetch(PDO::FETCH_ASSOC);
$_SESSION['member_id'] = $account['member_id'];
$_SESSION['member_account_id'] = $account['id'];
$_SESSION['member_username'] = $account['username'];
$_SESSION['member_full_name'] = $account['full_name'];
$_SESSION['member_title'] = $account['title'] ?? '';
}
unset($_SESSION['2fa_user_id']);
unset($_SESSION['2fa_user_type']);
unset($_SESSION['2fa_current_method']);
unset($_SESSION['2fa_account_data']);
header('Location: members/dashboard.php');
exit;
}
} else {
$error = "Invalid verification code. Please try again.";
$twoFA->logAttempt($userId, $method, false);
}
} elseif (isset($_POST['use_backup'])) {
$showBackupForm = true;
} elseif (isset($_POST['verify_backup'])) {
$code = trim($_POST['backup_code'] ?? '');
if ($twoFA->verifyBackupCode($userId, $code)) {
$twoFA->logAttempt($userId, 'backup', true);
// Complete login (same as above)
if ($userType === 'admin') {
$db = Database::getInstance()->getConnection();
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$userId]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $user['username'];
$_SESSION['email'] = $user['email'];
$_SESSION['full_name'] = $user['full_name'];
$_SESSION['access_level'] = $user['access_level'];
$_SESSION['logged_in'] = true;
unset($_SESSION['2fa_user_id']);
unset($_SESSION['2fa_user_type']);
unset($_SESSION['2fa_current_method']);
header('Location: dashboard.php');
exit;
} else {
// Member login - restore account data from session
$account = $_SESSION['2fa_account_data'] ?? null;
if ($account) {
$_SESSION['member_id'] = $account['member_id'];
$_SESSION['member_account_id'] = $account['id'];
$_SESSION['member_username'] = $account['username'];
$_SESSION['member_full_name'] = $account['full_name'];
$_SESSION['member_title'] = $account['title'] ?? '';
} else {
// Fallback: query from database
$db = Database::getInstance()->getConnection();
$stmt = $db->prepare("SELECT * FROM member_accounts WHERE member_id = ?");
$stmt->execute([$userId]);
$account = $stmt->fetch(PDO::FETCH_ASSOC);
$_SESSION['member_id'] = $account['member_id'];
$_SESSION['member_account_id'] = $account['id'];
$_SESSION['member_username'] = $account['username'];
$_SESSION['member_full_name'] = $account['full_name'];
$_SESSION['member_title'] = $account['title'] ?? '';
}
unset($_SESSION['2fa_user_id']);
unset($_SESSION['2fa_user_type']);
unset($_SESSION['2fa_current_method']);
unset($_SESSION['2fa_account_data']);
header('Location: members/dashboard.php');
exit;
}
} else {
$error = "Invalid backup code.";
$twoFA->logAttempt($userId, 'backup', false);
}
} elseif (isset($_POST['send_email_otp'])) {
$twoFA->generateOTP($userId, 'email');
$showEmailOTP = true;
} elseif (isset($_POST['send_sms_otp'])) {
$twoFA->generateOTP($userId, 'sms');
$showSMSOTP = true;
}
}
// Auto-send OTP if using email or SMS method
if ($currentMethod === 'email' && !$showEmailOTP && !isset($_POST['verify_code']) && !isset($_POST['switch_method'])) {
$twoFA->generateOTP($userId, 'email');
$showEmailOTP = true;
}
if ($currentMethod === 'sms' && !$showSMSOTP && !isset($_POST['verify_code']) && !isset($_POST['switch_method'])) {
$twoFA->generateOTP($userId, 'sms');
$showSMSOTP = true;
}
// Get settings for display
$stmt = Database::getInstance()->getConnection()->prepare("SELECT setting_value FROM system_settings WHERE setting_key = 'site_title'");
$stmt->execute();
$siteTitle = $stmt->fetchColumn() ?: 'Church Portal';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Two-Factor Verification - <?php echo htmlspecialchars($siteTitle); ?></title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
</head>
<body class="bg-gradient-to-br from-blue-50 via-purple-50 to-pink-50 min-h-screen flex items-center justify-center p-4">
<div class="max-w-md w-full">
<!-- Logo/Header -->
<div class="text-center mb-8">
<div class="inline-block p-4 bg-gradient-to-r from-blue-600 to-purple-600 rounded-full mb-4">
<i class="fas fa-shield-alt text-4xl text-white"></i>
</div>
<h1 class="text-3xl font-bold text-gray-800 mb-2">Two-Factor Verification</h1>
<p class="text-gray-600">Enter your verification code to continue</p>
</div>
<!-- Error Message -->
<?php if ($error): ?>
<div class="bg-red-50 border border-red-200 text-red-800 px-4 py-3 rounded-lg mb-6">
<i class="fas fa-exclamation-circle mr-2"></i><?php echo htmlspecialchars($error); ?>
</div>
<?php endif; ?>
<!-- Method Selector (if multiple methods enabled) -->
<?php if (count($enabledMethods) > 1 && !$showBackupForm): ?>
<div class="bg-white rounded-xl shadow-lg p-6 mb-6">
<h3 class="text-sm font-semibold text-gray-700 mb-3">Choose Verification Method:</h3>
<div class="grid grid-cols-<?php echo min(count($enabledMethods), 3); ?> gap-3">
<?php if (in_array('totp', $enabledMethods)): ?>
<form method="POST">
<input type="hidden" name="method" value="totp">
<button type="submit" name="switch_method"
class="w-full px-4 py-3 rounded-lg border-2 transition-all <?php echo $currentMethod === 'totp' ? 'border-blue-500 bg-blue-50' : 'border-gray-200 hover:border-blue-300'; ?>">
<i class="fas fa-mobile-alt text-2xl mb-1 <?php echo $currentMethod === 'totp' ? 'text-blue-600' : 'text-gray-600'; ?>"></i>
<div class="text-xs font-medium <?php echo $currentMethod === 'totp' ? 'text-blue-800' : 'text-gray-700'; ?>">Authenticator</div>
</button>
</form>
<?php endif; ?>
<?php if (in_array('email', $enabledMethods)): ?>
<form method="POST">
<input type="hidden" name="method" value="email">
<button type="submit" name="switch_method"
class="w-full px-4 py-3 rounded-lg border-2 transition-all <?php echo $currentMethod === 'email' ? 'border-purple-500 bg-purple-50' : 'border-gray-200 hover:border-purple-300'; ?>">
<i class="fas fa-envelope text-2xl mb-1 <?php echo $currentMethod === 'email' ? 'text-purple-600' : 'text-gray-600'; ?>"></i>
<div class="text-xs font-medium <?php echo $currentMethod === 'email' ? 'text-purple-800' : 'text-gray-700'; ?>">Email OTP</div>
</button>
</form>
<?php endif; ?>
<?php if (in_array('sms', $enabledMethods)): ?>
<form method="POST">
<input type="hidden" name="method" value="sms">
<button type="submit" name="switch_method"
class="w-full px-4 py-3 rounded-lg border-2 transition-all <?php echo $currentMethod === 'sms' ? 'border-green-500 bg-green-50' : 'border-gray-200 hover:border-green-300'; ?>">
<i class="fas fa-sms text-2xl mb-1 <?php echo $currentMethod === 'sms' ? 'text-green-600' : 'text-gray-600'; ?>"></i>
<div class="text-xs font-medium <?php echo $currentMethod === 'sms' ? 'text-green-800' : 'text-gray-700'; ?>">SMS OTP</div>
</button>
</form>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<!-- Verification Card -->
<div class="bg-white rounded-2xl shadow-2xl p-8">
<?php if ($showBackupForm): ?>
<!-- Backup Code Form -->
<div class="text-center mb-6">
<i class="fas fa-key text-4xl text-yellow-600 mb-3"></i>
<h2 class="text-xl font-bold text-gray-800">Enter Backup Code</h2>
<p class="text-sm text-gray-600 mt-2">Use one of your saved backup codes</p>
</div>
<form method="POST">
<input type="text" name="backup_code" required
class="w-full px-4 py-3 border-2 border-gray-300 rounded-lg text-center text-2xl font-mono tracking-widest uppercase mb-4 focus:border-blue-500 focus:outline-none"
placeholder="XXXXXXXX" maxlength="8" autofocus>
<button type="submit" name="verify_backup"
class="w-full py-3 bg-gradient-to-r from-yellow-600 to-orange-600 text-white rounded-lg font-semibold hover:shadow-lg transition-all">
<i class="fas fa-check mr-2"></i>Verify Backup Code
</button>
</form>
<div class="text-center mt-4">
<a href="verify-2fa.php" class="text-blue-600 hover:underline">
<i class="fas fa-arrow-left mr-2"></i>Back to main verification
</a>
</div>
<?php elseif ($showEmailOTP || $showSMSOTP): ?>
<!-- OTP Sent Message -->
<div class="text-center mb-6">
<i class="fas fa-envelope text-4xl text-purple-600 mb-3"></i>
<h2 class="text-xl font-bold text-gray-800">Code Sent!</h2>
<p class="text-sm text-gray-600 mt-2">
A verification code has been sent to your
<?php echo $showEmailOTP ? 'email' : 'phone'; ?>
</p>
</div>
<form method="POST">
<label class="block text-sm font-medium text-gray-700 mb-2">Verification Code:</label>
<input type="text" name="code" maxlength="6" pattern="[0-9]{6}" required
class="w-full px-4 py-3 border-2 border-gray-300 rounded-lg text-center text-3xl tracking-widest mb-4 focus:border-blue-500 focus:outline-none"
placeholder="000000" autofocus>
<button type="submit" name="verify_code"
class="w-full py-3 bg-gradient-to-r from-blue-600 to-purple-600 text-white rounded-lg font-semibold hover:shadow-lg transition-all">
<i class="fas fa-check-circle mr-2"></i>Verify Code
</button>
</form>
<div class="text-center mt-4">
<form method="POST" class="inline">
<button type="submit" name="send_<?php echo $showEmailOTP ? 'email' : 'sms'; ?>_otp"
class="text-blue-600 hover:underline">
<i class="fas fa-redo mr-2"></i>Resend Code
</button>
</form>
</div>
<?php else: ?>
<!-- TOTP Code Form -->
<div class="text-center mb-6">
<i class="fas fa-mobile-alt text-4xl text-blue-600 mb-3"></i>
<h2 class="text-xl font-bold text-gray-800">Authenticator Code</h2>
<p class="text-sm text-gray-600 mt-2">Enter the code from your authenticator app</p>
</div>
<form method="POST">
<input type="text" name="code" maxlength="6" pattern="[0-9]{6}" required
class="w-full px-4 py-3 border-2 border-gray-300 rounded-lg text-center text-3xl tracking-widest mb-4 focus:border-blue-500 focus:outline-none"
placeholder="000000" autofocus>
<button type="submit" name="verify_code"
class="w-full py-3 bg-gradient-to-r from-blue-600 to-purple-600 text-white rounded-lg font-semibold hover:shadow-lg transition-all">
<i class="fas fa-check-circle mr-2"></i>Verify Code
</button>
</form>
<?php endif; ?>
<!-- Alternative Options -->
<?php if (!$showBackupForm): ?>
<div class="mt-6 pt-6 border-t border-gray-200">
<p class="text-sm text-gray-600 text-center mb-3">Having trouble?</p>
<div class="space-y-2">
<?php if ($settings['method'] === 'totp'): ?>
<form method="POST">
<button type="submit" name="send_email_otp"
class="w-full py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 text-sm">
<i class="fas fa-envelope mr-2"></i>Send code via email
</button>
</form>
<?php endif; ?>
<form method="POST">
<button type="submit" name="use_backup"
class="w-full py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 text-sm">
<i class="fas fa-key mr-2"></i>Use backup code
</button>
</form>
</div>
</div>
<?php endif; ?>
<!-- Cancel Link -->
<div class="text-center mt-6">
<a href="logout.php" class="text-gray-500 hover:text-gray-700 text-sm">
<i class="fas fa-times mr-2"></i>Cancel and logout
</a>
</div>
</div>
<!-- Help Text -->
<div class="mt-6 text-center text-sm text-gray-600">
<i class="fas fa-info-circle mr-2"></i>
Lost your device? Contact your administrator for help.
</div>
</div>
<script>
// Auto-focus on input
document.addEventListener('DOMContentLoaded', function() {
const input = document.querySelector('input[name="code"], input[name="backup_code"]');
if (input) {
input.focus();
// Auto-submit when 6 digits entered (for TOTP/OTP)
if (input.name === 'code') {
input.addEventListener('input', function(e) {
if (e.target.value.length === 6) {
// Small delay before auto-submit
setTimeout(() => {
e.target.form.submit();
}, 300);
}
});
}
}
});
</script>
</body>
</html>
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists