diff --git a/app/pages/credentials.php b/app/pages/credentials.php new file mode 100644 index 0000000..6c4e273 --- /dev/null +++ b/app/pages/credentials.php @@ -0,0 +1,159 @@ +verifyCsrfToken($_POST['csrf_token'] ?? '')) { + Feedback::flash('ERROR', 'DEFAULT', 'Invalid security token. Please try again.'); + header("Location: $app_root?page=credentials"); + exit(); + } + + // Apply rate limiting + require_once '../app/includes/rate_limit_middleware.php'; + checkRateLimit($db, 'credentials', $user_id); + + switch ($item) { + case '2fa': + require_once '../app/helpers/2fa.php'; + + switch ($action) { + case 'setup': + // Validate the setup code + $code = $_POST['code'] ?? ''; + $secret = $_POST['secret'] ?? ''; + + if ($userObject->enableTwoFactor($user_id, $secret, $code)) { + Feedback::flash('NOTICE', 'DEFAULT', 'Two-factor authentication has been enabled successfully.'); + header("Location: $app_root?page=credentials"); + exit(); + } else { + Feedback::flash('ERROR', 'DEFAULT', 'Invalid verification code. Please try again.'); + header("Location: $app_root?page=credentials&action=edit"); + exit(); + } + break; + + case 'verify': + $code = $_POST['code'] ?? ''; + if ($userObject->verifyTwoFactor($user_id, $code)) { + $_SESSION['2fa_verified'] = true; + header("Location: $app_root?page=dashboard"); + exit(); + } else { + Feedback::flash('ERROR', 'DEFAULT', 'Invalid verification code. Please try again.'); + header("Location: $app_root?page=credentials&action=verify"); + exit(); + } + break; + + case 'disable': + if ($userObject->disableTwoFactor($user_id)) { + Feedback::flash('NOTICE', 'DEFAULT', 'Two-factor authentication has been disabled.'); + } else { + Feedback::flash('ERROR', 'DEFAULT', 'Failed to disable two-factor authentication.'); + } + header("Location: $app_root?page=credentials"); + exit(); + break; + } + break; + + case 'password': + require_once '../app/classes/validator.php'; + + $validator = new Validator($_POST); + $rules = [ + 'current_password' => [ + 'required' => true, + 'min' => 8 + ], + 'new_password' => [ + 'required' => true, + 'min' => 8 + ], + 'confirm_password' => [ + 'required' => true, + 'matches' => 'new_password' + ] + ]; + + if (!$validator->validate($rules)) { + Feedback::flash('ERROR', 'DEFAULT', $validator->getFirstError()); + header("Location: $app_root?page=credentials"); + exit(); + } + + if ($userObject->changePassword($user_id, $_POST['current_password'], $_POST['new_password'])) { + Feedback::flash('NOTICE', 'DEFAULT', 'Password has been changed successfully.'); + } else { + Feedback::flash('ERROR', 'DEFAULT', 'Failed to change password. Please verify your current password.'); + } + header("Location: $app_root?page=credentials"); + exit(); + break; + } + +// no form submitted, show the templates +} else { + // Get user timezone for templates + $userTimezone = !empty($userDetails[0]['timezone']) ? $userDetails[0]['timezone'] : 'UTC'; + + // Generate CSRF token if not exists + require_once '../app/helpers/security.php'; + $security = SecurityHelper::getInstance(); + $security->generateCsrfToken(); + + // Get 2FA status for the template + $has2fa = $userObject->isTwoFactorEnabled($user_id); + + switch ($action) { + case 'edit': + if (!$has2fa) { + require_once '../app/helpers/2fa.php'; + $secret = $userObject->generateTwoFactorSecret(); + $qrCode = $userObject->generateTwoFactorQR($user_id, $secret); + $backupCodes = $userObject->generateBackupCodes(); + } + // Get any new feedback messages + include '../app/helpers/feedback.php'; + + // Load the 2FA setup template + include '../app/templates/credentials-2fa-setup.php'; + break; + + case 'verify': + // Get any new feedback messages + include '../app/helpers/feedback.php'; + + // Load the 2FA verification template + include '../app/templates/credentials-2fa-verify.php'; + break; + + default: + // Get any new feedback messages + include '../app/helpers/feedback.php'; + + // Load the combined management template + include '../app/templates/credentials-manage.php'; + } +} diff --git a/app/templates/credentials-2fa-setup.php b/app/templates/credentials-2fa-setup.php new file mode 100644 index 0000000..9f70586 --- /dev/null +++ b/app/templates/credentials-2fa-setup.php @@ -0,0 +1,109 @@ + + +
Two-factor authentication adds an extra layer of security to your account. Once enabled, you'll need to enter both your password and a code from your authenticator app when signing in.
+If you haven't already, install an authenticator app on your mobile device:
+Open your authenticator app and scan this QR code:
+ +
+ Enter the 6-digit code from your authenticator app to verify the setup:
+ + + ++ Important: Save these backup codes in a secure place. + If you lose access to your authenticator app, you can use these codes to sign in. + Each code can only be used once. +
+
+
+ Enter the 6-digit code from your authenticator app:
+ + + +
+ Lost access to your authenticator app?
+
+ Use a backup code
+
+
Two-factor authentication adds an extra layer of security to your account. Once enabled, you'll need to enter both your password and a code from your authenticator app when signing in.
+ + ++ + Two-factor authentication is enabled +
+ + Your account is protected with an authenticator app + ++ + Two-factor authentication is not enabled +
+ + Add an extra layer of security to your account by requiring both your password and an authentication code + +