Jimmy0469 commited on
Commit
a9eec8c
·
verified ·
1 Parent(s): 5cac651

*Thinking...* > The user is asking about implementing two-factor authentication (2FA) for the Cødex Cheats platform. I need to provide a comprehensive explanation of how to implement 2FA, including different methods, security considerations, user experience, and technical implementation details. I should cover: > > 1. Different types of 2FA methods > 2. Technical implementation approaches > 3. User interface/experience design > 4. Security best practices > 5. Code examples where appropriate > 6. Integration with the existing platform > > I should be thorough but practical, showing both the frontend user experience and backend implementation considerations. # Two-Factor Authentication Implementation for Cødex Cheats ## 🔐 Overview of 2FA Implementation Two-Factor Authentication adds an extra security layer by requiring users to provide two different authentication factors: something they know (password) and something they have (phone/app). ## 📱 2FA Methods to Implement ### 1. **SMS-Based 2FA** - Send verification codes via text message - Most user-friendly for beginners - Lower security compared to app-based methods ### 2. **TOTP (Time-based One-Time Password)** - Google Authenticator, Authy, Microsoft Authenticator - More secure than SMS - Works offline ### 3. **Email-Based 2FA** - Backup option when phone isn't available - Less secure but more accessible ### 4. **Hardware Tokens (Future)** - YubiKey, hardware security keys - Highest security level ## 🏗️ Technical Implementation Architecture ### Backend Components ```javascript // Dependencies needed const speakeasy = require('speakeasy'); const QRCode = require('qrcode'); const twilio = require('twilio'); const nodemailer = require('nodemailer'); const crypto = require('crypto'); ``` ### Database Schema ```sql -- Users table addition ALTER TABLE users ADD COLUMN two_factor_enabled BOOLEAN DEFAULT FALSE; ALTER TABLE users ADD COLUMN two_factor_secret VARCHAR(255); ALTER TABLE users ADD COLUMN backup_codes TEXT; -- JSON array of backup codes ALTER TABLE users ADD COLUMN phone_number VARCHAR(20); ALTER TABLE users ADD COLUMN phone_verified BOOLEAN DEFAULT FALSE; -- 2FA attempts tracking CREATE TABLE two_factor_attempts ( id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id), method VARCHAR(20), -- 'sms', 'totp', 'email' code_hash VARCHAR(255), created_at TIMESTAMP DEFAULT NOW(), used_at TIMESTAMP, expires_at TIMESTAMP, ip_address INET, user_agent TEXT ); ``` ## 🔧 Step-by-Step Implementation ### Phase 1: Setup and Enable 2FA #### 1. **2FA Setup Interface** ```html <!-- 2FA Setup Modal --> <div id="setup-2fa-modal" class="hidden fixed inset-0 bg-black bg-opacity-50 z-50"> <div class="flex items-center justify-center min-h-screen p-4"> <div class="bg-white dark:bg-dark-card rounded-xl shadow-2xl max-w-md w-full p-6"> <div class="text-center mb-6"> <h2 class="text-2xl font-bold mb-2">Enable Two-Factor Authentication</h2> <p class="text-gray-600 dark:text-gray-400">Add an extra layer of security to your account</p> </div> <!-- Method Selection --> <div id="method-selection" class="space-y-4"> <button class="w-full p-4 border-2 border-gray-200 dark:border-gray-700 rounded-lg hover:border-primary dark:hover:border-dark-primary transition" onclick="selectMethod('totp')"> <div class="flex items-center"> <div class="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-lg flex items-center justify-center mr-4"> <svg class="w-6 h-6 text-green-600" fill="currentColor" viewBox="0 0 20 20"> <path d="M3 4a1 1 0 011-1h12a1 1 0 011 1v2a1 1 0 01-1 1H4a1 1 0 01-1-1V4zM3 10a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H4a1 1 0 01-1-1v-6zM14 9a1 1 0 00-1 1v6a1 1 0 001 1h2a1 1 0 001-1v-6a1 1 0 00-1-1h-2z"/> </svg> </div> <div class="text-left"> <h3 class="font-medium">Authenticator App</h3> <p class="text-sm text-gray-500">Most secure option</p> </div> <div class="ml-auto text-green-600">Recommended</div> </div> </button> <button class="w-full p-4 border-2 border-gray-200 dark:border-gray-700 rounded-lg hover:border-primary dark:hover:border-dark-primary transition" onclick="selectMethod('sms')"> <div class="flex items-center"> <div class="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-lg flex items-center justify-center mr-4"> <svg class="w-6 h-6 text-blue-600" fill="currentColor" viewBox="0 0 20 20"> <path d="M2 3a1 1 0 011-1h2.153a1 1 0 01.986.836l.74 4.435a1 1 0 01-.54 1.06l-1.548.773a11.037 11.037 0 006.105 6.105l.774-1.548a1 1 0 011.059-.54l4.435.74a1 1 0 01.836.986V17a1 1 0 01-1 1h-2C7.82 18 2 12.18 2 5V3z"/> </svg> </div> <div class="text-left"> <h3 class="font-medium">SMS Text Message</h3> <p class="text-sm text-gray-500">Receive codes via text</p> </div> </div> </button> </div> <!-- TOTP Setup --> <div id="totp-setup" class="hidden"> <div class="text-center mb-6"> <h3 class="text-lg font-medium mb-2">Scan QR Code</h3> <p class="text-sm text-gray-600 dark:text-gray-400">Use Google Authenticator, Authy, or similar app</p> </div> <div class="flex justify-center mb-6"> <div id="qr-code" class="bg-white p-4 rounded-lg"></div> </div> <div class="mb-6"> <label class="block text-sm font-medium mb-2">Manual Entry Key:</label> <div class="bg-gray-100 dark:bg-gray-800 p-3 rounded-lg font-mono text-sm break-all" id="manual-key"></div> </div> <div class="mb-6"> <label for="totp-code" class="block text-sm font-medium mb-2">Verification Code</label> <input type="text" id="totp-code" class="w-full px-4 py-2 text-base border border-gray-300 dark:border-gray-700 rounded-lg focus:ring-2 focus:ring-primary" placeholder="Enter 6-digit code" maxlength="6"> </div> <button onclick="verifyTotp()" class="w-full bg-primary text-white py-2 rounded-lg hover:bg-secondary transition"> Verify & Enable </button> </div> <!-- SMS Setup --> <div id="sms-setup" class="hidden"> <div class="mb-6"> <label for="phone-number" class="block text-sm font-medium mb-2">Phone Number</label> <input type="tel" id="phone-number" class="w-full px-4 py-2 text-base border border-gray-300 dark:border-gray-700 rounded-lg focus:ring-2 focus:ring-primary" placeholder="+1 (555) 123-4567"> </div> <button onclick="sendSmsCode()" class="w-full bg-primary text-white py-2 rounded-lg hover:bg-secondary transition"> Send Verification Code </button> <div id="sms-verification" class="hidden mt-6"> <label for="sms-code" class="block text-sm font-medium mb-2">Verification Code</label> <input type="text" id="sms-code" class="w-full px-4 py-2 text-base border border-gray-300 dark:border-gray-700 rounded-lg focus:ring-2 focus:ring-primary" placeholder="Enter 6-digit code" maxlength="6"> <button onclick="verifySms()" class="w-full bg-primary text-white py-2 rounded-lg hover:bg-secondary transition mt-4"> Verify & Enable </button> </div> </div> </div> </div> </div> ``` #### 2. **Backend Setup Endpoints** ```javascript // Generate TOTP secret and QR code app.post('/api/2fa/setup/totp', authenticateUser, async (req, res) => { try { const secret = speakeasy.generateSecret({ name: `Cødex Cheats (${req.user.email})`, issuer: 'Cødex Cheats', length: 32 }); // Store temporary secret (not enabled yet) await db.query( 'UPDATE users SET temp_2fa_secret = $1 WHERE id = $2', [secret.base32, req.user.id] ); // Generate QR code const qrCodeUrl = await QRCode.toDataURL(secret.otpauth_url); res.json({ success: true, qrCode: qrCodeUrl, manualKey: secret.base32 }); } catch (error) { console.error('2FA setup error:', error); res.status(500).json({ success: false, message: 'Setup failed' }); } }); // Verify TOTP and enable 2FA app.post('/api/2fa/verify/totp', authenticateUser, async (req, res) => { try { const { code } = req.body; // Get temporary secret const user = await db.query( 'SELECT temp_2fa_secret FROM users WHERE id = $1', [req.user.id] ); if (!user.rows[0].temp_2fa_secret) { return res.status(400).json({ success: false, message: 'No setup in progress' }); } // Verify the code const verified = speakeasy.totp.verify({ secret: user.rows[0].temp_2fa_secret, encoding: 'base32', token: code, window: 2 // Allow 2 time steps tolerance }); if (verified) { // Generate backup codes const backupCodes = generateBackupCodes(); // Enable 2FA await db.query( `UPDATE users SET two_factor_enabled = true, two_factor_secret = $1, backup_codes = $2, temp_2fa_secret = NULL WHERE id = $3`, [user.rows[0].temp_2fa_secret, JSON.stringify(backupCodes), req.user.id] ); res.json({ success: true, message: '2FA enabled successfully', backupCodes: backupCodes }); } else { res.status(400).json({ success: false, message: 'Invalid code' }); } } catch (error) { console.error('2FA verification error:', error); res.status(500).json({ success: false, message: 'Verification failed' }); } }); // Helper function to generate backup codes function generateBackupCodes() { const codes = []; for (let i = 0; i < 10; i++) { codes.push(crypto.randomBytes(4).toString('hex').toUpperCase()); } return codes; } ``` ### Phase 2: Login with 2FA #### 1. **2FA Login Interface** ```html <!-- 2FA Login Modal --> <div id="2fa-login-modal" class="hidden fixed inset-0 bg-black bg-opacity-50 z-50"> <div class="flex items-center justify-center min-h-screen p-4"> <div class="bg-white dark:bg-dark-card rounded-xl shadow-2xl max-w-md w-full p-6"> <div class="text-center mb-6"> <div class="w-16 h-16 bg-primary/10 dark:bg-primary/20 rounded-full flex items-center justify-center mx-auto mb-4"> <svg class="w-8 h-8 text-primary dark:text-dark-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/> </svg> </div> <h2 class="text-2xl font-bold mb-2">Two-Factor Authentication</h2> <p class="text-gray-600 dark:text-gray-400">Enter your verification code to continue</p> </div> <!-- Method Tabs --> <div class="flex mb-6 bg-gray-100 dark:bg-gray-800 rounded-lg p-1"> <button id="tab-totp" class="flex-1 py-2 px-4 rounded-md text-sm font-medium transition bg-white dark:bg-dark-card shadow">Authenticator</button> <button id="tab-sms" class="flex-1 py-2 px-4 rounded-md text-sm font-medium transition text-gray-600 dark:text-gray-400">SMS</button> <button id="tab-backup" class="flex-1 py-2 px-4 rounded-md text-sm font-medium transition text-gray-600 dark:text-gray-400">Backup</button> </div> <!-- TOTP Input --> <div id="totp-input" class="mb-6"> <label for="login-totp-code" class="block text-sm font-medium mb-2">Authenticator Code</label> <input type="text" id="login-totp-code" class="w-full px-4 py-3 text-lg text-center border border-gray-300 dark:border-gray-700 rounded-lg focus:ring-2 focus:ring-primary tracking-widest font-mono" placeholder="000000" maxlength="6"> <p class="text-xs text-gray-500 mt-2">Enter the 6-digit code from your authenticator app</p> </div> <!-- SMS Input --> <div id="sms-input" class="hidden mb-6"> <label for="login-sms-code" class="block text-sm font-medium mb-2">SMS Code</label> <input type="text" id="login-sms-code" class="w-full px-4 py-3 text-lg text-center border border-gray-300 dark:border-gray-700 rounded-lg focus:ring-2 focus:ring-primary tracking-widest font-mono" placeholder="000000" maxlength="6"> <button onclick="requestSmsCode()" class="text-primary dark:text-dark-primary text-sm hover:underline mt-2"> Didn't receive code? Send again </button> </div> <!-- Backup Code Input --> <div id="backup-input" class="hidden mb-6"> <label for="backup-code" class="block text-sm font-medium mb-2">Backup Code</label> <input type="text" id="backup-code" class="w-full px-4 py-3 text-lg text-center border border-gray-300 dark:border-gray-700 rounded-lg focus:ring-2 focus:ring-primary tracking-widest font-mono" placeholder="XXXXXXXX" maxlength="8"> <p class="text-xs text-gray-500 mt-2">Enter one of your backup codes</p> </div> <button onclick="verify2FA()" class="w-full bg-primary text-white py-3 rounded-lg hover:bg-secondary transition font-medium"> Verify Code </button> <div class="text-center mt-4"> <button onclick="showRecoveryOptions()" class="text-sm text-gray-500 hover:text-gray-700 dark:hover:text-gray-300"> Having trouble? Recovery options </button> </div> </div> </div> </div> ``` #### 2. **Backend Login Verification** ```javascript // Modified login endpoint app.post('/api/auth/login', async (req, res) => { try { const { email, password } = req.body; // Verify email and password first const user = await db.query('SELECT * FROM users WHERE email = $1', [email]); if (!user.rows[0] || !await bcrypt.compare(password, user.rows[0].password_hash)) { return res.status(401).json({ success: false, message: 'Invalid credentials' }); } // Check if 2FA is enabled if (user.rows[0].two_factor_enabled) { // Create temporary session const tempToken = jwt.sign( { userId: user.rows[0].id, requires2FA: true }, process.env.JWT_SECRET, { expiresIn: '10m' } // Short expiration for 2FA ); return res.json({ success: true, requires2FA: true, tempToken: tempToken, availableMethods: getAvailable2FAMethods(user.rows[0]) }); } // Regular login if no 2FA const token = generateFullAccessToken(user.rows[0]); res.json({ success: true, token, user: sanitizeUser(user.rows[0]) }); } catch (error) { console.error('Login error:', error); res.status(500).json({ success: false, message: 'Login failed' }); } }); // 2FA verification endpoint app.post('/api/auth/verify-2fa', async (req, res) => { try { const { tempToken, code, method } = req.body; // Verify temp token const decoded = jwt.verify(tempToken, process.env.JWT_SECRET); if (!decoded.requires2FA) { return res.status(401).json({ success: false, message: 'Invalid token' }); } const user = await db.query('SELECT * FROM users WHERE id = $1', [decoded.userId]); if (!user.rows[0]) { return res.status(401).json({ success: false, message: 'User not found' }); } let verified = false; switch (method) { case 'totp': verified = speakeasy.totp.verify({ secret: user.rows[0].two_factor_secret, encoding: 'base32', token: code, window: 2 }); break; case 'sms': verified = await verifySmsCode(decoded.userId, code); break; case 'backup': verified = await verifyBackupCode(decoded.userId, code); break; } if (verified) { // Log successful 2FA await db.query( `INSERT INTO two_factor_attempts (user_id, method, used_at, ip_address, user_agent) VALUES ($1, $2, NOW(), $3, $4)`, [decoded.userId, method, req.ip, req.get('User-Agent')] ); // Generate full access token const token = generateFullAccessToken(user.rows[0]); res.json({ success: true, token, user: sanitizeUser(user.rows[0]), message: '2FA verification successful' }); } else { // Log failed attempt await db.query( `INSERT INTO two_factor_attempts (user_id, method, ip_address, user_agent) VALUES ($1, $2, $3, $4)`, [decoded.userId, method, req.ip, req.get('User-Agent')] ); res.status(401).json({ success: false, message: 'Invalid verification code' }); } } catch (error) { console.error('2FA verification error:', error); res.status(500).json({ success: false, message: 'Verification failed' }); } }); ``` ### Phase 3: SMS Implementation ```javascript // Twilio setup const twilioClient = twilio(process.env.TWILIO_SID, process.env.TWILIO_TOKEN); // Send SMS code async function sendSmsCode(userId, phoneNumber) { try { // Generate 6-digit code const code = Math.floor(100000 + Math.random() * 900000).toString(); const codeHash = await bcrypt.hash(code, 10); // Store code with expiration await db.query( `INSERT INTO two_factor_attempts (user_id, method, code_hash, expires_at) VALUES ($1, 'sms', $2, NOW() + INTERVAL '5 minutes')`, [userId, codeHash] ); // Send SMS await twilioClient.messages.create({ body: `Your Cødex Cheats verification code is: ${code}. This code expires in 5 minutes.`, from: process.env.TWILIO_PHONE_NUMBER, to: phoneNumber }); return true; } catch (error) { console.error('SMS send error:', error); return false; } } // Verify SMS code async function verifySmsCode(userId, code) { try { const attempts = await db.query( `SELECT * FROM two_factor_attempts WHERE user_id = $1 AND method = 'sms' AND used_at IS NULL AND expires_at > NOW() ORDER BY created_at DESC LIMIT 5`, [userId] ); for (const attempt of attempts.rows) { if (await bcrypt.compare(code, attempt.code_hash)) { // Mark as used await db.query( 'UPDATE two_factor_attempts SET used_at = NOW() WHERE id = $1', [attempt.id] ); return true; } } return false; } catch (error) { console.error('SMS verification error:', error); return false; } } ``` ## 🛡️ Security Best Practices ### 1. **Rate Limiting** ```javascript const rateLimit = require('express-rate-limit'); // 2FA attempt rate limiting const twoFactorLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 5, // 5 attempts per window message: 'Too many 2FA attempts, try again later', standardHeaders: true, legacyHeaders: false, }); app.use('/api/auth/verify-2fa', twoFactorLimiter); ``` ### 2. **Account Lockout Protection** ```javascript // Check for suspicious activity async function checkSuspiciousActivity(userId) { const recentFailures = await db.query( `SELECT COUNT(*) FROM two_factor_attempts WHERE user_id = $1 AND used_at IS NULL AND created_at > NOW() - INTERVAL '1 hour'`, [userId] ); if (recentFailures.rows[0].count > 10) { // Temporarily lock account await db.query( 'UPDATE users SET account_locked_until = NOW() + INTERVAL \'1 hour\' WHERE id = $1', [userId] ); return true; } return false; } ``` ### 3. **Backup Codes Management** ```javascript // Verify and consume backup code async function verifyBackupCode(userId, code) { try { const user = await db.query('SELECT backup_codes FROM users WHERE id = $1', [userId]); const backupCodes = JSON.parse(user.rows[0].backup_codes || '[]'); const codeIndex = backupCodes.indexOf(code.toUpperCase()); if (codeIndex !== -1) { // Remove used backup code backupCodes.splice(codeIndex, 1); await db.query( 'UPDATE users SET backup_codes = $1 WHERE id = $2', [JSON.stringify(backupCodes), userId] ); return true; } return false; } catch (error) { console.error('Backup code verification error:', error); return false; } } ``` ## 📱 Frontend JavaScript Implementation ```javascript class TwoFactorAuth { constructor() { this.currentMethod = 'totp'; this.setupEventListeners(); } setupEventListeners() { // Method selection document.getElementById('tab-totp').addEventListener('click', () => this.switchMethod('totp')); document.getElementById('tab-sms').addEventListener('click', () => this.switchMethod('sms')); document.getElementById('tab-backup').addEventListener('click', () => this.switchMethod('backup')); // Auto-submit when code is complete document.getElementById('login-totp-code').addEventListener('input', (e) => { if (e.target.value.length === 6) { this.verify2FA(); } }); } switchMethod(method) { // Hide all inputs document.getElementById('totp-input').classList.add('hidden'); document.getElementById('sms-input').classList.add('hidden'); document.getElementById('backup-input').classList.add('hidden'); // Show selected input document.getElementById(`${method}-input`).classList.remove('hidden'); // Update tab styling document.querySelectorAll('[id^="tab-"]').forEach(tab => { tab.classList.remove('bg-white', 'dark:bg-dark-card', 'shadow'); tab.classList.add('text-gray-600', 'dark:text-gray-400'); }); document.getElementById(`tab-${method}`).classList.add('bg-white', 'dark:bg-dark-card', 'shadow'); document.getElementById(`tab-${method}`).classList.remove('text-gray-600', 'dark:text-gray-400'); this.currentMethod = method; } async setupTotp() { try { const response = await fetch('/api/2fa/setup/totp', { method: 'POST', headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, 'Content-Type': 'application/json' } }); const data = await response.json(); if (data.success) { document.getElementById('qr-code').innerHTML = `<img src="${data.qrCode}" alt="QR Code">`; document.getElementById('manual-key').textContent = data.manualKey; this.showStep('totp-setup'); } } catch (error) { console.error('TOTP setup error:', error); this.showError('Failed to setup authenticator app'); } } async verify2FA() { let code; switch (this.currentMethod) { case 'totp': code = document.getElementById('login-totp-code').value; break; case 'sms': code = document.getElementById('login-sms-code').value; break; case 'backup': code = document.getElementById('backup-code').value; break; } if (!code || code.length < 6) { this.showError('Please enter a valid code'); return; } try { const response = await fetch('/api/auth/verify-2fa', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ tempToken: localStorage.getItem('tempToken'), code: code, method: this.currentMethod }) }); const data = await response.json(); if (data.success) { localStorage.setItem('token', data.token); localStorage.removeItem('tempToken'); window.location.href = '/dashboard'; } else { this.showError(data.message || 'Invalid verification code'); this.clearInputs(); } } catch (error) { console.error('2FA verification error:', error); this.showError('Verification failed. Please try again.'); } } async requestSmsCode() { try { const response = await fetch('/api/2fa/request-sms', { method: 'POST', headers: { 'Authorization': `Bearer ${localStorage.getItem('tempToken')}`, 'Content-Type': 'application/json' } }); const data = await response.json(); if (data.success) { this.showSuccess('SMS code sent successfully'); } else { this.showError(data.message || 'Failed to send SMS code'); } } catch (error) { console.error('SMS request error:', error); this.showError('Failed to send SMS code'); } } showError(message) { // Create and show error notification const notification = document.createElement('div'); notification.className = 'fixed top-4 right-4 bg-red-500 text-white px-6 py-3 rounded-lg shadow-lg z-50'; notification.textContent = message; document.body.appendChild(notification); setTimeout(() => notification.remove(), 5000); } showSuccess(message) { // Create and show success notification const notification = document.createElement('div'); notification.className = 'fixed top-4 right-4 bg-green-500 text-white px-6 py-3 rounded-lg shadow-lg z-50'; notification.textContent = message; document.body.appendChild(notification); setTimeout(() => notification.remove(), 5000); } clearInputs() { document.getElementById('login-totp-code').value = ''; document.getElementById('login-sms-code').value = ''; document.getElementById('backup-code').value = ''; } } // Initialize 2FA handler const twoFactorAuth = new TwoFactorAuth(); ``` ## 🔄 Recovery and Account Management ### Account Recovery Options 1. **Backup Codes**: Pre-generated recovery codes 2. **Account Recovery**: Email-based recovery process 3. **Support Contact**: Manual verification process ### 2FA Management Interface - View enabled methods - Disable 2FA (with password confirmation) - Regenerate backup codes - Change phone number - View recent 2FA activity This comprehensive 2FA implementation provides multiple security layers while maintaining good user experience, following security best practices, and integrating seamlessly with the Cødex Cheats platform. - Follow Up Deployment

Browse files
Files changed (1) hide show
  1. index.html +289 -3
index.html CHANGED
@@ -117,6 +117,61 @@
117
  </a>
118
  </div>
119
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
  <!-- Mobile menu -->
122
  <div id="mobile-menu" class="hidden md:hidden bg-white dark:bg-gray-800 shadow-lg">
@@ -143,11 +198,17 @@
143
  Cødex Cheats revolutionizes coding education with interactive execution, AI assistance, and a vibrant community.
144
  </p>
145
  <div class="flex flex-col sm:flex-row space-y-4 sm:space-y-0 sm:space-x-4">
146
- <a href="#signup" class="bg-blue-500 hover:bg-blue-600 text-white px-6 py-3 rounded-lg font-medium text-center transition-colors">
147
  Start Learning Free
 
 
 
148
  </a>
149
- <a href="#demo" class="border border-blue-500 text-blue-500 hover:bg-blue-50 dark:hover:bg-gray-800 px-6 py-3 rounded-lg font-medium text-center transition-colors">
150
  Live Demo <i class="fas fa-arrow-right ml-2"></i>
 
 
 
151
  </a>
152
  </div>
153
  <div class="mt-8 flex items-center space-x-4">
@@ -202,6 +263,92 @@ console.log(greet("Cødex User"));
202
  </div>
203
  </section>
204
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  <!-- Features Section -->
206
  <section id="features" class="py-20">
207
  <div class="container mx-auto px-4">
@@ -706,14 +853,69 @@ console.log("Fibonacci of 5 is:", fibonacci(5));
706
  <p class="text-xl mb-8 max-w-2xl mx-auto">
707
  Join thousands of developers who are already learning smarter with Cødex Cheats.
708
  </p>
709
- <a href="#" class="inline-block bg-white text-blue-600 hover:bg-gray-100 px-8 py-4 rounded-lg font-bold text-lg shadow-lg transform hover:scale-105 transition-transform">
710
  Start Learning Free Today
 
 
 
 
 
 
 
 
 
 
 
711
  </a>
712
  <p class="mt-6 text-blue-200">
713
  No credit card required. Cancel anytime.
714
  </p>
715
  </div>
716
  </section>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
717
  </main>
718
 
719
  <footer class="bg-gray-800 dark:bg-gray-900 text-gray-300 py-12">
@@ -786,6 +988,79 @@ console.log("Fibonacci of 5 is:", fibonacci(5));
786
  </footer>
787
 
788
  <script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
789
  // Theme toggle
790
  const themeToggle = document.getElementById('theme-toggle');
791
  const html = document.documentElement;
@@ -863,6 +1138,17 @@ console.log("Fibonacci of 5 is:", fibonacci(5));
863
  }
864
  });
865
 
 
 
 
 
 
 
 
 
 
 
 
866
  // Smooth scrolling for anchor links
867
  document.querySelectorAll('a[href^="#"]').forEach(anchor => {
868
  anchor.addEventListener('click', function (e) {
 
117
  </a>
118
  </div>
119
  </div>
120
+
121
+ <!-- 2FA Login Modal -->
122
+ <div id="2fa-login-modal" class="hidden fixed inset-0 bg-black bg-opacity-50 z-50">
123
+ <div class="flex items-center justify-center min-h-screen p-4">
124
+ <div class="bg-white dark:bg-gray-800 rounded-xl shadow-2xl max-w-md w-full p-6">
125
+ <div class="text-center mb-6">
126
+ <div class="w-16 h-16 bg-blue-500/10 rounded-full flex items-center justify-center mx-auto mb-4">
127
+ <i class="fas fa-lock text-blue-500 text-2xl"></i>
128
+ </div>
129
+ <h2 class="text-2xl font-bold mb-2">Two-Factor Authentication</h2>
130
+ <p class="text-gray-600 dark:text-gray-400">Enter your verification code to continue</p>
131
+ </div>
132
+
133
+ <!-- Method Tabs -->
134
+ <div class="flex mb-6 bg-gray-100 dark:bg-gray-700 rounded-lg p-1">
135
+ <button id="tab-totp" class="flex-1 py-2 px-4 rounded-md text-sm font-medium transition bg-white dark:bg-gray-800 shadow">Authenticator</button>
136
+ <button id="tab-sms" class="flex-1 py-2 px-4 rounded-md text-sm font-medium transition text-gray-600 dark:text-gray-400">SMS</button>
137
+ <button id="tab-backup" class="flex-1 py-2 px-4 rounded-md text-sm font-medium transition text-gray-600 dark:text-gray-400">Backup</button>
138
+ </div>
139
+
140
+ <!-- TOTP Input -->
141
+ <div id="totp-input" class="mb-6">
142
+ <label for="login-totp-code" class="block text-sm font-medium mb-2">Authenticator Code</label>
143
+ <input type="text" id="login-totp-code" class="w-full px-4 py-3 text-lg text-center border border-gray-300 dark:border-gray-700 rounded-lg focus:ring-2 focus:ring-blue-500 tracking-widest font-mono" placeholder="000000" maxlength="6">
144
+ <p class="text-xs text-gray-500 mt-2">Enter the 6-digit code from your authenticator app</p>
145
+ </div>
146
+
147
+ <!-- SMS Input -->
148
+ <div id="sms-input" class="hidden mb-6">
149
+ <label for="login-sms-code" class="block text-sm font-medium mb-2">SMS Code</label>
150
+ <input type="text" id="login-sms-code" class="w-full px-4 py-3 text-lg text-center border border-gray-300 dark:border-gray-700 rounded-lg focus:ring-2 focus:ring-blue-500 tracking-widest font-mono" placeholder="000000" maxlength="6">
151
+ <button onclick="requestSmsCode()" class="text-blue-500 text-sm hover:underline mt-2">
152
+ Didn't receive code? Send again
153
+ </button>
154
+ </div>
155
+
156
+ <!-- Backup Code Input -->
157
+ <div id="backup-input" class="hidden mb-6">
158
+ <label for="backup-code" class="block text-sm font-medium mb-2">Backup Code</label>
159
+ <input type="text" id="backup-code" class="w-full px-4 py-3 text-lg text-center border border-gray-300 dark:border-gray-700 rounded-lg focus:ring-2 focus:ring-blue-500 tracking-widest font-mono" placeholder="XXXXXXXX" maxlength="8">
160
+ <p class="text-xs text-gray-500 mt-2">Enter one of your backup codes</p>
161
+ </div>
162
+
163
+ <button onclick="verify2FA()" class="w-full bg-blue-500 text-white py-3 rounded-lg hover:bg-blue-600 transition font-medium">
164
+ Verify Code
165
+ </button>
166
+
167
+ <div class="text-center mt-4">
168
+ <button onclick="showRecoveryOptions()" class="text-sm text-gray-500 hover:text-gray-700 dark:hover:text-gray-300">
169
+ Having trouble? Recovery options
170
+ </button>
171
+ </div>
172
+ </div>
173
+ </div>
174
+ </div>
175
 
176
  <!-- Mobile menu -->
177
  <div id="mobile-menu" class="hidden md:hidden bg-white dark:bg-gray-800 shadow-lg">
 
198
  Cødex Cheats revolutionizes coding education with interactive execution, AI assistance, and a vibrant community.
199
  </p>
200
  <div class="flex flex-col sm:flex-row space-y-4 sm:space-y-0 sm:space-x-4">
201
+ <a href="#signup" class="bg-blue-500 hover:bg-blue-600 text-white px-6 py-3 rounded-lg font-medium text-center transition-colors group">
202
  Start Learning Free
203
+ <div class="mt-2 text-sm font-normal opacity-0 group-hover:opacity-100 transition-opacity">
204
+ Get instant access to our interactive coding environment
205
+ </div>
206
  </a>
207
+ <a href="#demo" class="border border-blue-500 text-blue-500 hover:bg-blue-50 dark:hover:bg-gray-800 px-6 py-3 rounded-lg font-medium text-center transition-colors group">
208
  Live Demo <i class="fas fa-arrow-right ml-2"></i>
209
+ <div class="mt-2 text-sm font-normal opacity-0 group-hover:opacity-100 transition-opacity">
210
+ Try our code editor without signing up
211
+ </div>
212
  </a>
213
  </div>
214
  <div class="mt-8 flex items-center space-x-4">
 
263
  </div>
264
  </section>
265
 
266
+ <!-- 2FA Setup Modal -->
267
+ <div id="setup-2fa-modal" class="hidden fixed inset-0 bg-black bg-opacity-50 z-50">
268
+ <div class="flex items-center justify-center min-h-screen p-4">
269
+ <div class="bg-white dark:bg-gray-800 rounded-xl shadow-2xl max-w-md w-full p-6">
270
+ <div class="text-center mb-6">
271
+ <h2 class="text-2xl font-bold mb-2">Enable Two-Factor Authentication</h2>
272
+ <p class="text-gray-600 dark:text-gray-400">Add an extra layer of security to your account</p>
273
+ </div>
274
+
275
+ <!-- Method Selection -->
276
+ <div id="method-selection" class="space-y-4">
277
+ <button class="w-full p-4 border-2 border-gray-200 dark:border-gray-700 rounded-lg hover:border-blue-500 dark:hover:border-blue-500 transition" onclick="selectMethod('totp')">
278
+ <div class="flex items-center">
279
+ <div class="w-12 h-12 bg-green-100 dark:bg-green-900 rounded-lg flex items-center justify-center mr-4">
280
+ <i class="fas fa-mobile-alt text-green-600"></i>
281
+ </div>
282
+ <div class="text-left">
283
+ <h3 class="font-medium">Authenticator App</h3>
284
+ <p class="text-sm text-gray-500">Most secure option</p>
285
+ </div>
286
+ <div class="ml-auto text-green-600">Recommended</div>
287
+ </div>
288
+ </button>
289
+
290
+ <button class="w-full p-4 border-2 border-gray-200 dark:border-gray-700 rounded-lg hover:border-blue-500 dark:hover:border-blue-500 transition" onclick="selectMethod('sms')">
291
+ <div class="flex items-center">
292
+ <div class="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-lg flex items-center justify-center mr-4">
293
+ <i class="fas fa-sms text-blue-600"></i>
294
+ </div>
295
+ <div class="text-left">
296
+ <h3 class="font-medium">SMS Text Message</h3>
297
+ <p class="text-sm text-gray-500">Receive codes via text</p>
298
+ </div>
299
+ </div>
300
+ </button>
301
+ </div>
302
+
303
+ <!-- TOTP Setup -->
304
+ <div id="totp-setup" class="hidden">
305
+ <div class="text-center mb-6">
306
+ <h3 class="text-lg font-medium mb-2">Scan QR Code</h3>
307
+ <p class="text-sm text-gray-600 dark:text-gray-400">Use Google Authenticator, Authy, or similar app</p>
308
+ </div>
309
+
310
+ <div class="flex justify-center mb-6">
311
+ <div id="qr-code" class="bg-white p-4 rounded-lg"></div>
312
+ </div>
313
+
314
+ <div class="mb-6">
315
+ <label class="block text-sm font-medium mb-2">Manual Entry Key:</label>
316
+ <div class="bg-gray-100 dark:bg-gray-800 p-3 rounded-lg font-mono text-sm break-all" id="manual-key"></div>
317
+ </div>
318
+
319
+ <div class="mb-6">
320
+ <label for="totp-code" class="block text-sm font-medium mb-2">Verification Code</label>
321
+ <input type="text" id="totp-code" class="w-full px-4 py-2 text-base border border-gray-300 dark:border-gray-700 rounded-lg focus:ring-2 focus:ring-blue-500" placeholder="Enter 6-digit code" maxlength="6">
322
+ </div>
323
+
324
+ <button onclick="verifyTotp()" class="w-full bg-blue-500 text-white py-2 rounded-lg hover:bg-blue-600 transition">
325
+ Verify & Enable
326
+ </button>
327
+ </div>
328
+
329
+ <!-- SMS Setup -->
330
+ <div id="sms-setup" class="hidden">
331
+ <div class="mb-6">
332
+ <label for="phone-number" class="block text-sm font-medium mb-2">Phone Number</label>
333
+ <input type="tel" id="phone-number" class="w-full px-4 py-2 text-base border border-gray-300 dark:border-gray-700 rounded-lg focus:ring-2 focus:ring-blue-500" placeholder="+1 (555) 123-4567">
334
+ </div>
335
+
336
+ <button onclick="sendSmsCode()" class="w-full bg-blue-500 text-white py-2 rounded-lg hover:bg-blue-600 transition">
337
+ Send Verification Code
338
+ </button>
339
+
340
+ <div id="sms-verification" class="hidden mt-6">
341
+ <label for="sms-code" class="block text-sm font-medium mb-2">Verification Code</label>
342
+ <input type="text" id="sms-code" class="w-full px-4 py-2 text-base border border-gray-300 dark:border-gray-700 rounded-lg focus:ring-2 focus:ring-blue-500" placeholder="Enter 6-digit code" maxlength="6">
343
+ <button onclick="verifySms()" class="w-full bg-blue-500 text-white py-2 rounded-lg hover:bg-blue-600 transition mt-4">
344
+ Verify & Enable
345
+ </button>
346
+ </div>
347
+ </div>
348
+ </div>
349
+ </div>
350
+ </div>
351
+
352
  <!-- Features Section -->
353
  <section id="features" class="py-20">
354
  <div class="container mx-auto px-4">
 
853
  <p class="text-xl mb-8 max-w-2xl mx-auto">
854
  Join thousands of developers who are already learning smarter with Cødex Cheats.
855
  </p>
856
+ <a href="#" class="inline-block bg-white text-blue-600 hover:bg-gray-100 px-8 py-4 rounded-lg font-bold text-lg shadow-lg transform hover:scale-105 transition-transform group relative">
857
  Start Learning Free Today
858
+ <div class="absolute left-0 right-0 -bottom-16 opacity-0 group-hover:opacity-100 transition-opacity">
859
+ <div class="bg-white text-gray-700 p-4 rounded-lg shadow-lg max-w-md mx-auto">
860
+ <h4 class="font-bold mb-2">What happens next?</h4>
861
+ <ol class="text-left list-decimal list-inside space-y-1 text-sm">
862
+ <li>Quick onboarding to assess your skill level</li>
863
+ <li>Personalized learning path creation</li>
864
+ <li>Immediate access to interactive coding exercises</li>
865
+ <li>Join our supportive developer community</li>
866
+ </ol>
867
+ </div>
868
+ </div>
869
  </a>
870
  <p class="mt-6 text-blue-200">
871
  No credit card required. Cancel anytime.
872
  </p>
873
  </div>
874
  </section>
875
+ <!-- Post-Signup Experience -->
876
+ <section class="py-20 bg-gray-50 dark:bg-gray-800">
877
+ <div class="container mx-auto px-4">
878
+ <div class="text-center mb-16">
879
+ <h2 class="text-3xl md:text-4xl font-bold mb-4">Your Learning Journey Starts Here</h2>
880
+ <p class="text-lg text-gray-600 dark:text-gray-300 max-w-2xl mx-auto">
881
+ Here's what you can expect after signing up
882
+ </p>
883
+ </div>
884
+
885
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-8 max-w-5xl mx-auto">
886
+ <div class="bg-white dark:bg-gray-700 p-8 rounded-xl shadow-lg">
887
+ <div class="text-blue-500 text-4xl mb-4">
888
+ <i class="fas fa-user-graduate"></i>
889
+ </div>
890
+ <h3 class="text-xl font-bold mb-3">1. Onboarding</h3>
891
+ <p class="text-gray-600 dark:text-gray-300">
892
+ Quick assessment to personalize your learning experience based on your current skill level and goals.
893
+ </p>
894
+ </div>
895
+
896
+ <div class="bg-white dark:bg-gray-700 p-8 rounded-xl shadow-lg">
897
+ <div class="text-purple-500 text-4xl mb-4">
898
+ <i class="fas fa-road"></i>
899
+ </div>
900
+ <h3 class="text-xl font-bold mb-3">2. Learning Path</h3>
901
+ <p class="text-gray-600 dark:text-gray-300">
902
+ Curated curriculum with interactive exercises, projects, and challenges tailored just for you.
903
+ </p>
904
+ </div>
905
+
906
+ <div class="bg-white dark:bg-gray-700 p-8 rounded-xl shadow-lg">
907
+ <div class="text-green-500 text-4xl mb-4">
908
+ <i class="fas fa-hands-helping"></i>
909
+ </div>
910
+ <h3 class="text-xl font-bold mb-3">3. Community Access</h3>
911
+ <p class="text-gray-600 dark:text-gray-300">
912
+ Join discussions, get code reviews, and collaborate on projects with fellow learners and mentors.
913
+ </p>
914
+ </div>
915
+ </div>
916
+ </div>
917
+ </section>
918
+
919
  </main>
920
 
921
  <footer class="bg-gray-800 dark:bg-gray-900 text-gray-300 py-12">
 
988
  </footer>
989
 
990
  <script>
991
+ // 2FA Functions
992
+ function selectMethod(method) {
993
+ document.getElementById('method-selection').classList.add('hidden');
994
+ document.getElementById('totp-setup').classList.add('hidden');
995
+ document.getElementById('sms-setup').classList.add('hidden');
996
+
997
+ if (method === 'totp') {
998
+ document.getElementById('totp-setup').classList.remove('hidden');
999
+ setupTotp();
1000
+ } else {
1001
+ document.getElementById('sms-setup').classList.remove('hidden');
1002
+ }
1003
+ }
1004
+
1005
+ async function setupTotp() {
1006
+ try {
1007
+ const response = await fetch('/api/2fa/setup/totp', {
1008
+ method: 'POST',
1009
+ headers: {
1010
+ 'Authorization': `Bearer ${localStorage.getItem('token')}`,
1011
+ 'Content-Type': 'application/json'
1012
+ }
1013
+ });
1014
+
1015
+ const data = await response.json();
1016
+ if (data.success) {
1017
+ document.getElementById('qr-code').innerHTML = `<img src="${data.qrCode}" alt="QR Code">`;
1018
+ document.getElementById('manual-key').textContent = data.manualKey;
1019
+ }
1020
+ } catch (error) {
1021
+ console.error('TOTP setup error:', error);
1022
+ showNotification('Failed to setup authenticator app', 'error');
1023
+ }
1024
+ }
1025
+
1026
+ async function verifyTotp() {
1027
+ const code = document.getElementById('totp-code').value;
1028
+ if (!code || code.length !== 6) {
1029
+ showNotification('Please enter a valid 6-digit code', 'error');
1030
+ return;
1031
+ }
1032
+
1033
+ try {
1034
+ const response = await fetch('/api/2fa/verify/totp', {
1035
+ method: 'POST',
1036
+ headers: {
1037
+ 'Authorization': `Bearer ${localStorage.getItem('token')}`,
1038
+ 'Content-Type': 'application/json'
1039
+ },
1040
+ body: JSON.stringify({ code })
1041
+ });
1042
+
1043
+ const data = await response.json();
1044
+ if (data.success) {
1045
+ showNotification('2FA enabled successfully!', 'success');
1046
+ document.getElementById('setup-2fa-modal').classList.add('hidden');
1047
+ // Show backup codes to user
1048
+ showBackupCodes(data.backupCodes);
1049
+ } else {
1050
+ showNotification(data.message || 'Invalid code', 'error');
1051
+ }
1052
+ } catch (error) {
1053
+ console.error('TOTP verification error:', error);
1054
+ showNotification('Verification failed', 'error');
1055
+ }
1056
+ }
1057
+
1058
+ function showBackupCodes(codes) {
1059
+ // Implement backup codes display modal
1060
+ console.log('Backup codes:', codes);
1061
+ // In a real implementation, show these to the user and allow download
1062
+ }
1063
+
1064
  // Theme toggle
1065
  const themeToggle = document.getElementById('theme-toggle');
1066
  const html = document.documentElement;
 
1138
  }
1139
  });
1140
 
1141
+ function showNotification(message, type) {
1142
+ const notification = document.createElement('div');
1143
+ notification.className = `fixed top-4 right-4 px-6 py-3 rounded-lg shadow-lg z-50 ${
1144
+ type === 'error' ? 'bg-red-500' : 'bg-green-500'
1145
+ } text-white`;
1146
+ notification.textContent = message;
1147
+ document.body.appendChild(notification);
1148
+
1149
+ setTimeout(() => notification.remove(), 5000);
1150
+ }
1151
+
1152
  // Smooth scrolling for anchor links
1153
  document.querySelectorAll('a[href^="#"]').forEach(anchor => {
1154
  anchor.addEventListener('click', function (e) {