Server : LiteSpeed
System : Linux terra.hostitbro.com 5.14.0-611.54.3.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Thu May 7 16:31:24 EDT 2026 x86_64
User : outerorb ( 1091)
PHP Version : 8.1.34
Disable Function : mail
Directory :  /home2/outerorb/emp.outerorbittech.in/

📁 Create New:
⬆️ Upload File:
Current Dir [ Writable ] Root [ Writable ]


OR Upload from URL:
URL: Save as:

📄 File: 2fa-verify.php

Path: /home2/outerorb/emp.outerorbittech.in/2fa-verify.php

Size: 11.44 KB

Permissions: 0666

<?php
require __DIR__ . '/includes/helpers.php';

// Check if user is in 2FA verification state
if (!isset($_SESSION['user_id_temp']) || !isset($_SESSION['role_temp'])) {
    redirect_with_message('index.php', 'Please login first.', 'error');
}

$flash = flash();
$error = '';
$remaining_attempts = 3;

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // CSRF check
    if (!isset($_POST['csrf_token']) || !verify_csrf($_POST['csrf_token'])) {
        $error = 'Invalid session token. Please try again.';
    } else {
        $token_type = sanitize_text($_POST['token_type'] ?? 'totp');
        $token = sanitize_text($_POST['token'] ?? '');
        $user_id = $_SESSION['user_id_temp'];
        
        if ($token_type === 'totp') {
            // Verify TOTP token
            if (verify_2fa_token($user_id, $token)) {
                // Success! Create session
                clear_rate_limit('2fa_' . $user_id);
                regenerate_session_id();
                
                $redirectRole = $_SESSION['role_temp'];
                $pendingData  = $_SESSION['pending_session_data'] ?? null;

                if ($redirectRole === 'employee') {
                    $_SESSION['employee_logged_in'] = true;
                    $_SESSION['employee'] = $pendingData;
                } elseif ($redirectRole === 'admin') {
                    $_SESSION['admin_logged_in'] = true;
                    $_SESSION['admin'] = $pendingData;
                }

                // Clear temporary session vars
                unset($_SESSION['user_id_temp'], $_SESSION['role_temp'], $_SESSION['pending_session_data']);

                $dashboard = $redirectRole === 'admin' ? 'admin/dashboard.php' : 'employee/dashboard.php';
                header('Location: ' . $dashboard);
                exit;
            } else {
                // Rate limit 2FA attempts
                $rateLimitKey = '2fa_' . $user_id;
                check_rate_limit($rateLimitKey, 3, 300);
                $error = 'Invalid authenticator code. Please try again.';
            }
        } elseif ($token_type === 'backup') {
            // Verify backup code
            $pdo = db();
            try {
                $stmt = $pdo->prepare("
                    SELECT id FROM two_factor_backups 
                    WHERE user_id = ? AND used_at IS NULL 
                    AND backup_code = ?
                    LIMIT 1
                ");
                $stmt->execute([$user_id, $token]);
                $backup = $stmt->fetch();
                
                if ($backup) {
                    // Mark backup code as used
                    $pdo->prepare("UPDATE two_factor_backups SET used_at = NOW() WHERE id = ?")->execute([$backup['id']]);
                    
                    // Create session
                    clear_rate_limit('2fa_' . $user_id);
                    regenerate_session_id();
                    
                    $redirectRole = $_SESSION['role_temp'];
                    $pendingData  = $_SESSION['pending_session_data'] ?? null;

                    if ($redirectRole === 'employee') {
                        $_SESSION['employee_logged_in'] = true;
                        $_SESSION['employee'] = $pendingData;
                    } elseif ($redirectRole === 'admin') {
                        $_SESSION['admin_logged_in'] = true;
                        $_SESSION['admin'] = $pendingData;
                    }

                    unset($_SESSION['user_id_temp'], $_SESSION['role_temp'], $_SESSION['pending_session_data']);

                    $dashboard = $redirectRole === 'admin' ? 'admin/dashboard.php' : 'employee/dashboard.php';
                    header('Location: ' . $dashboard);
                    exit;
                } else {
                    $error = 'Invalid backup code.';
                }
            } catch (Exception $e) {
                $error = 'Error verifying backup code.';
            }
        } else {
            $error = 'Invalid verification method.';
        }
    }
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Two-Factor Authentication - Outer Orbit HRMS</title>
    <link rel="stylesheet" href="assets/css/style.css?v=<?php echo filemtime(__DIR__ . '/assets/css/style.css'); ?>" />
    <link rel="stylesheet" href="assets/css/polish.css?v=<?php echo filemtime(__DIR__ . '/assets/css/polish.css'); ?>" />
    <style>
        .auth-wrap { max-width: 440px; margin: 60px auto 0; }
        .auth-logo { text-align: center; margin-bottom: 28px; }
        .auth-logo h1 { font-size: 1.5rem; margin: 0 0 4px; color: #111827; }
        .auth-logo p { margin: 0; color: #6b7280; font-size: .875rem; }
        .auth-tabs { display: flex; gap: 0; margin-bottom: 24px; border: 1px solid #e5e7eb; border-radius: 8px; overflow: hidden; }
        .auth-tab { flex: 1; padding: 10px; text-align: center; cursor: pointer; background: #f9fafb; border: none; font-size: .9rem; font-weight: 600; color: #6b7280; transition: background .15s, color .15s; }
        .auth-tab.active { background: #2563eb; color: #fff; }
        .input-label { display: block; font-size: .85rem; font-weight: 600; color: #374151; margin-bottom: 5px; }
        .tab-content { display: none; }
        .tab-content.active { display: block; }
        .backup-info { background: #f0f9ff; border-left: 4px solid #2563eb; padding: 12px; margin: 16px 0; border-radius: 4px; font-size: .875rem; color: #1e40af; }
        .text-center { text-align: center; }
        .text-sm { font-size: .875rem; }
    </style>
</head>
<body style="background: #f3f4f6; min-height: 100vh;">

<div class="auth-wrap">
    <div class="auth-logo">
        <h1>Outer Orbit Technologies</h1>
        <p>Two-Factor Authentication</p>
    </div>

    <div class="card">
        <?php if ($flash): ?>
            <div class="alert <?php echo $flash['type'] === 'error' ? 'alert-error' : 'alert-success'; ?>">
                <?php echo htmlspecialchars($flash['message'], ENT_QUOTES, 'UTF-8'); ?>
            </div>
        <?php endif; ?>
        <?php if ($error): ?>
            <div class="alert alert-error"><?php echo htmlspecialchars($error, ENT_QUOTES, 'UTF-8'); ?></div>
        <?php endif; ?>

        <p style="text-align: center; color: #6b7280; margin-bottom: 24px;" class="text-sm">
            Enter the 6-digit code from your authenticator app
        </p>

        <!-- Auth method tabs -->
        <div class="auth-tabs">
            <button type="button" class="auth-tab active" data-tab="totp">Authenticator</button>
            <button type="button" class="auth-tab" data-tab="backup">Backup Code</button>
        </div>

        <form method="post" action="2fa-verify.php" novalidate>
            <input type="hidden" name="csrf_token" value="<?php echo csrf_token(); ?>">
            <input type="hidden" name="token_type" id="token-type" value="totp">

            <!-- TOTP Tab -->
            <div id="totp-tab" class="tab-content active">
                <div style="display: flex; flex-direction: column; gap: 16px;">
                    <div>
                        <label class="input-label" for="totp">Authenticator Code</label>
                        <input 
                            id="totp" 
                            type="text" 
                            inputmode="numeric"
                            pattern="[0-9]{6}"
                            maxlength="6"
                            required 
                            autocomplete="off"
                            placeholder="000000"
                            style="width: 100%; box-sizing: border-box; font-size: 1.5rem; letter-spacing: 8px; text-align: center; font-weight: bold;" 
                        />
                        <p style="margin: 8px 0 0 0; font-size: .8rem; color: #6b7280;">
                            Enter the 6-digit code from your authenticator app (Google Authenticator, Microsoft Authenticator, Authy, etc.)
                        </p>
                    </div>
                    <button type="submit" style="width: 100%;" class="btn btn-primary">Verify Code</button>
                </div>
            </div>

            <!-- Backup Code Tab -->
            <div id="backup-tab" class="tab-content">
                <div style="display: flex; flex-direction: column; gap: 16px;">
                    <div class="backup-info">
                        💡 Use this if you don't have access to your authenticator app. Each backup code can be used only once.
                    </div>
                    <div>
                        <label class="input-label" for="backup">Backup Code</label>
                        <input 
                            id="backup" 
                            type="text" 
                            required 
                            autocomplete="off"
                            placeholder="Enter your backup code"
                            style="width: 100%; box-sizing: border-box;" 
                        />
                        <p style="margin: 8px 0 0 0; font-size: .8rem; color: #6b7280;">
                            You saved these backup codes when you first enabled two-factor authentication.
                        </p>
                    </div>
                    <button type="submit" style="width: 100%;" class="btn btn-primary">Verify Backup Code</button>
                </div>
            </div>
        </form>

        <hr style="margin: 24px 0; border: none; border-top: 1px solid #e5e7eb;">
        
        <p style="text-align: center; font-size: .85rem; color: #6b7280;">
            Having trouble? <a href="index.php" style="color: #2563eb; text-decoration: none;">Start over</a>
        </p>
    </div>
</div>

<script>
(function() {
    const tabs = document.querySelectorAll('.auth-tab');
    const totpInput = document.getElementById('totp');
    const backupInput = document.getElementById('backup');
    const tokenTypeInput = document.getElementById('token-type');

    tabs.forEach(tab => {
        tab.addEventListener('click', function() {
            const tabName = this.getAttribute('data-tab');
            
            // Update active tab
            tabs.forEach(t => t.classList.remove('active'));
            this.classList.add('active');
            
            // Update active content
            document.querySelectorAll('.tab-content').forEach(content => {
                content.classList.remove('active');
            });
            document.getElementById(tabName + '-tab').classList.add('active');
            
            // Update hidden token type
            tokenTypeInput.value = tabName;
            
            // Clear and focus appropriate input
            if (tabName === 'totp') {
                backupInput.value = '';
                totpInput.focus();
            } else {
                totpInput.value = '';
                backupInput.focus();
            }
        });
    });

    // Auto-submit when 6 digits entered in TOTP
    totpInput.addEventListener('input', function() {
        this.value = this.value.replace(/[^0-9]/g, '').slice(0, 6);
        if (this.value.length === 6) {
            document.querySelector('form').submit();
        }
    });

    // Focus TOTP input on load
    totpInput.focus();
})();
</script>

</body>
</html>

← Back to Directory Edit File 🔒 Chmod

WP File Manager