Sindbad~EG File Manager

Current Path : /home/copmadinaarea/thecopmadinaarea.org/portal/
Upload File :
Current File : /home/copmadinaarea/thecopmadinaarea.org/portal/verify-2fa.php

<?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