| 
									
										
										
										
											2024-06-28 17:05:32 +00:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-28 14:40:50 +00:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2024-11-29 16:08:56 +00:00
										 |  |  |  * User login | 
					
						
							| 
									
										
										
										
											2024-11-28 14:40:50 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2024-11-28 14:49:47 +00:00
										 |  |  |  * This page ("login") handles user login, session management, cookie handling, and error logging. | 
					
						
							| 
									
										
										
										
											2024-11-28 14:40:50 +00:00
										 |  |  |  * Supports "remember me" functionality to extend session duration. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Actions Performed: | 
					
						
							|  |  |  |  * - Validates login credentials. | 
					
						
							|  |  |  |  * - Manages session and cookies based on "remember me" option. | 
					
						
							|  |  |  |  * - Logs successful and failed login attempts. | 
					
						
							|  |  |  |  * - Displays login form and optional custom messages. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-01 09:45:07 +00:00
										 |  |  | // clear the global error var before login
 | 
					
						
							| 
									
										
										
										
											2024-06-28 17:05:32 +00:00
										 |  |  | unset($error); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | try { | 
					
						
							| 
									
										
										
										
											2024-08-10 18:42:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // connect to database
 | 
					
						
							| 
									
										
										
										
											2024-09-04 09:53:02 +00:00
										 |  |  |     $dbWeb = connectDB($config); | 
					
						
							| 
									
										
										
										
											2024-08-10 18:42:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |     // Initialize RateLimiter
 | 
					
						
							|  |  |  |     require_once '../app/classes/ratelimiter.php'; | 
					
						
							| 
									
										
										
										
											2025-01-06 09:31:07 +00:00
										 |  |  |     $rateLimiter = new RateLimiter($dbWeb['db']); | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-28 17:05:32 +00:00
										 |  |  |     if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) { | 
					
						
							| 
									
										
										
										
											2024-12-07 13:38:13 +00:00
										 |  |  |         try { | 
					
						
							| 
									
										
										
										
											2025-02-17 13:15:05 +00:00
										 |  |  |             // apply page rate limiting
 | 
					
						
							|  |  |  |             require_once '../app/includes/rate_limit_middleware.php'; | 
					
						
							|  |  |  |             checkRateLimit($dbWeb, 'login', null); // null since user is not logged in yet
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-30 16:48:46 +00:00
										 |  |  |             // Validate form data
 | 
					
						
							|  |  |  |             $security = SecurityHelper::getInstance(); | 
					
						
							|  |  |  |             $formData = $security->sanitizeArray($_POST, ['username', 'password', 'remember_me', 'csrf_token']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $validationRules = [ | 
					
						
							|  |  |  |                 'username' => [ | 
					
						
							|  |  |  |                     'type' => 'string', | 
					
						
							|  |  |  |                     'required' => true, | 
					
						
							|  |  |  |                     'min' => 3, | 
					
						
							|  |  |  |                     'max' => 20 | 
					
						
							|  |  |  |                 ], | 
					
						
							|  |  |  |                 'password' => [ | 
					
						
							|  |  |  |                     'type' => 'string', | 
					
						
							|  |  |  |                     'required' => true, | 
					
						
							|  |  |  |                     'min' => 2 | 
					
						
							|  |  |  |                 ] | 
					
						
							|  |  |  |             ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $errors = $security->validateFormData($formData, $validationRules); | 
					
						
							|  |  |  |             if (!empty($errors)) { | 
					
						
							|  |  |  |                 throw new Exception("Invalid input: " . implode(", ", $errors)); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-07 13:38:13 +00:00
										 |  |  |             $username = $_POST['username']; | 
					
						
							|  |  |  |             $password = $_POST['password']; | 
					
						
							| 
									
										
										
										
											2024-06-28 17:05:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |             // Check if IP is blacklisted
 | 
					
						
							|  |  |  |             if ($rateLimiter->isIpBlacklisted($user_IP)) { | 
					
						
							| 
									
										
										
										
											2025-02-16 08:18:26 +00:00
										 |  |  |                 throw new Exception(Feedback::get('LOGIN', 'IP_BLACKLISTED')['message']); | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Check rate limiting (but skip if IP is whitelisted)
 | 
					
						
							|  |  |  |             if (!$rateLimiter->isIpWhitelisted($user_IP)) { | 
					
						
							|  |  |  |                 $attempts = $rateLimiter->getRecentAttempts($user_IP); | 
					
						
							|  |  |  |                 if ($attempts >= $rateLimiter->maxAttempts) { | 
					
						
							| 
									
										
										
										
											2025-02-16 08:18:26 +00:00
										 |  |  |                     throw new Exception(Feedback::get('LOGIN', 'LOGIN_BLOCKED')['message']); | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-07 13:38:13 +00:00
										 |  |  |             // login successful
 | 
					
						
							|  |  |  |             if ( $userObject->login($username, $password) ) { | 
					
						
							|  |  |  |                 // if remember_me is checked, max out the session
 | 
					
						
							|  |  |  |                 if (isset($_POST['remember_me'])) { | 
					
						
							|  |  |  |                     // 30*24*60*60 = 30 days
 | 
					
						
							|  |  |  |                     $cookie_lifetime = 30 * 24 * 60 * 60; | 
					
						
							|  |  |  |                     $setcookie_lifetime = time() + 30 * 24 * 60 * 60; | 
					
						
							|  |  |  |                     $gc_maxlifetime = 30 * 24 * 60 * 60; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     // 0 - session end on browser close
 | 
					
						
							|  |  |  |                     // 1440 - 24 minutes (default)
 | 
					
						
							|  |  |  |                     $cookie_lifetime = 0; | 
					
						
							|  |  |  |                     $setcookie_lifetime = 0; | 
					
						
							|  |  |  |                     $gc_maxlifetime = 1440; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2024-06-30 07:49:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-17 12:36:00 +00:00
										 |  |  |                 // Configure secure session settings
 | 
					
						
							|  |  |  |                 ini_set('session.cookie_httponly', 1); | 
					
						
							|  |  |  |                 ini_set('session.use_only_cookies', 1); | 
					
						
							|  |  |  |                 ini_set('session.cookie_secure', isset($_SERVER['HTTPS']) ? 1 : 0); | 
					
						
							|  |  |  |                 ini_set('session.cookie_samesite', 'Strict'); | 
					
						
							|  |  |  |                 ini_set('session.gc_maxlifetime', $gc_maxlifetime); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // Regenerate session ID to prevent session fixation
 | 
					
						
							|  |  |  |                 session_regenerate_id(true); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-07 13:38:13 +00:00
										 |  |  |                 // set session lifetime and cookies
 | 
					
						
							|  |  |  |                 setcookie('username', $username, [ | 
					
						
							|  |  |  |                     'expires'	=> $setcookie_lifetime, | 
					
						
							|  |  |  |                     'path'		=> $config['folder'], | 
					
						
							|  |  |  |                     'domain'	=> $config['domain'], | 
					
						
							|  |  |  |                     'secure'	=> isset($_SERVER['HTTPS']), | 
					
						
							|  |  |  |                     'httponly'	=> true, | 
					
						
							|  |  |  |                     'samesite'	=> 'Strict' | 
					
						
							|  |  |  |                 ]); | 
					
						
							| 
									
										
										
										
											2024-07-03 06:37:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-17 12:36:00 +00:00
										 |  |  |                 // Set session variables
 | 
					
						
							|  |  |  |                 $_SESSION['USER_ID'] = $userObject->getUserId($username)[0]['id']; | 
					
						
							|  |  |  |                 $_SESSION['USERNAME'] = $username; | 
					
						
							|  |  |  |                 $_SESSION['LAST_ACTIVITY'] = time(); | 
					
						
							|  |  |  |                 if (isset($formData['remember_me'])) { | 
					
						
							|  |  |  |                     $_SESSION['REMEMBER_ME'] = true; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |                 // Log successful login
 | 
					
						
							| 
									
										
										
										
											2024-12-07 13:38:13 +00:00
										 |  |  |                 $user_id = $userObject->getUserId($username)[0]['id']; | 
					
						
							|  |  |  |                 $logObject->insertLog($user_id, "Login: User \"$username\" logged in. IP: $user_IP", 'user');
 | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 // Set success message and redirect
 | 
					
						
							| 
									
										
										
										
											2025-02-16 08:18:26 +00:00
										 |  |  |                 Feedback::flash('LOGIN', 'LOGIN_SUCCESS', null, true); | 
					
						
							| 
									
										
										
										
											2024-12-07 13:38:13 +00:00
										 |  |  |                 header('Location: ' . htmlspecialchars($app_root)); | 
					
						
							|  |  |  |                 exit(); | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2025-02-16 08:18:26 +00:00
										 |  |  |                 throw new Exception(Feedback::get('LOGIN', 'LOGIN_FAILED')['message']); | 
					
						
							| 
									
										
										
										
											2024-12-07 13:38:13 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |         } catch (Exception $e) { | 
					
						
							| 
									
										
										
										
											2025-01-04 09:46:07 +00:00
										 |  |  |             // Log the failed attempt
 | 
					
						
							| 
									
										
										
										
											2025-02-16 08:18:26 +00:00
										 |  |  |             Feedback::flash('ERROR', 'DEFAULT', $e->getMessage()); | 
					
						
							| 
									
										
										
										
											2025-01-04 09:46:07 +00:00
										 |  |  |             if (isset($username)) { | 
					
						
							|  |  |  |                 $user_id = $userObject->getUserId($username)[0]['id'] ?? 0; | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  |                 $logObject->insertLog($user_id, "Login: Failed login attempt for user \"$username\". IP: $user_IP. Reason: {$e->getMessage()}", 'user');
 | 
					
						
							| 
									
										
										
										
											2025-01-04 09:46:07 +00:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2024-06-28 17:05:32 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } catch (Exception $e) { | 
					
						
							| 
									
										
										
										
											2025-02-16 08:18:26 +00:00
										 |  |  |     Feedback::flash('ERROR', 'DEFAULT', 'There was an unexpected error. Please try again.'); | 
					
						
							| 
									
										
										
										
											2024-06-28 17:05:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  | // Show configured login message if any
 | 
					
						
							| 
									
										
										
										
											2024-08-01 08:12:54 +00:00
										 |  |  | if (!empty($config['login_message'])) { | 
					
						
							| 
									
										
										
										
											2025-02-16 08:18:26 +00:00
										 |  |  |     echo Feedback::render('NOTICE', 'DEFAULT', $config['login_message'], false, false, false); | 
					
						
							| 
									
										
										
										
											2024-08-01 08:12:54 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-17 08:24:50 +00:00
										 |  |  | // Get any new feedback messages
 | 
					
						
							| 
									
										
										
										
											2025-02-17 14:50:57 +00:00
										 |  |  | include '../app/helpers/feedback.php'; | 
					
						
							| 
									
										
										
										
											2025-01-06 09:13:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Load the template
 | 
					
						
							| 
									
										
										
										
											2024-08-12 11:12:24 +00:00
										 |  |  | include '../app/templates/form-login.php'; | 
					
						
							| 
									
										
										
										
											2024-06-28 17:05:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ?>
 |