Phase 2: Add comprehensive audit logging

- Created AuditLogger service class (360+ lines)
  * 16 action type constants (LOGIN_SUCCESS, PAYMENT_FAILURE, etc.)
  * log() - main logging method with flexible parameters
  * logLogin() - specialized login audit logging
  * logLogout() - session termination tracking
  * logPasswordChange() - credential change tracking
  * logBookingCreate() - booking audit trail
  * logPayment() - payment attempt/result tracking
  * logMembership() - membership action tracking
  * logAccessDenied() - authorization failure logging
  * getRecentLogs() - retrieve audit history
  * getLogsByAction() - filter logs by action type

- Integrated audit logging into validate_login.php:
  * Logs all login attempts (success and failures)
  * Captures failure reasons (invalid password, not verified, etc.)
  * Logs Google OAuth registrations and logins
  * Logs email/password login attempts
  * Captures IP address for each log entry
  * Includes timestamp (via database NOW())

- Audit Log Fields:
  * user_id - identifier of user performing action
  * action - action type (e.g., login_success)
  * status - success/failure/pending
  * ip_address - client IP (handles proxy/load balancer)
  * details - JSON-encoded metadata
  * created_at - timestamp

- Design Features:
  * Uses DatabaseService singleton for connections
  * Graceful error handling (doesn't break application)
  * JSON serialization of complex data for analysis
  * IP detection handles proxies and load balancers
  * Constants for action types enable IDE autocomplete
  * Extensible for additional event types

- Security Benefits:
  * Complete login audit trail for fraud detection
  * Failed login attempts tracked (detects brute force)
  * IP address recorded for geo-blocking/analysis
  * Timestamps enable timeline correlation
  * Action types enable targeted monitoring
This commit is contained in:
twotalesanimation
2025-12-02 21:13:16 +02:00
parent a4526979c4
commit 86f69474cc
2 changed files with 411 additions and 0 deletions

View File

@@ -8,6 +8,7 @@ require_once 'google-client/vendor/autoload.php'; // Add this line for Google Cl
use Middleware\CsrfMiddleware;
use Middleware\RateLimitMiddleware;
use Services\AuthenticationService;
use Services\AuditLogger;
// Check if connection is established
if (!$conn) {
@@ -70,6 +71,8 @@ if (isset($_GET['code'])) {
AuthenticationService::regenerateSession();
// Reset rate limit on successful login
RateLimitMiddleware::reset('login');
// Log successful registration via Google
AuditLogger::logLogin($email, true);
// echo json_encode(['status' => 'success', 'message' => 'Google login successful']);
header("Location: index.php");
exit();
@@ -89,6 +92,8 @@ if (isset($_GET['code'])) {
AuthenticationService::regenerateSession();
// Reset rate limit on successful login
RateLimitMiddleware::reset('login');
// Log successful Google login
AuditLogger::logLogin($email, true);
// echo json_encode(['status' => 'success', 'message' => 'Google login successful']);
header("Location: index.php");
exit();
@@ -122,12 +127,14 @@ if (isset($_POST['email']) && isset($_POST['password'])) {
if (empty($email) || empty($password)) {
echo json_encode(['status' => 'error', 'message' => 'Please enter both email and password.']);
RateLimitMiddleware::incrementAttempt('login', 900);
AuditLogger::logLogin($email ?? 'unknown', false, 'Empty email or password');
exit();
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo json_encode(['status' => 'error', 'message' => 'Invalid email format.']);
RateLimitMiddleware::incrementAttempt('login', 900);
AuditLogger::logLogin($email ?? 'unknown', false, 'Invalid email format');
exit();
}
@@ -152,6 +159,7 @@ if (isset($_POST['email']) && isset($_POST['password'])) {
if ($row['is_verified'] == 0) {
echo json_encode(['status' => 'error', 'message' => 'Your account is not verified. Please check your email for the verification link.']);
RateLimitMiddleware::incrementAttempt('login', 900);
AuditLogger::logLogin($email, false, 'Account not verified');
exit();
}
@@ -164,15 +172,19 @@ if (isset($_POST['email']) && isset($_POST['password'])) {
AuthenticationService::regenerateSession();
// Reset rate limit on successful login
RateLimitMiddleware::reset('login');
// Log successful email/password login
AuditLogger::logLogin($email, true);
echo json_encode(['status' => 'success', 'message' => 'Successful Login']);
} else {
// Password is incorrect - increment rate limit
RateLimitMiddleware::incrementAttempt('login', 900);
AuditLogger::logLogin($email, false, 'Invalid password');
echo json_encode(['status' => 'error', 'message' => 'Invalid password.']);
}
} else {
// User does not exist - still increment rate limit to prevent email enumeration
RateLimitMiddleware::incrementAttempt('login', 900);
AuditLogger::logLogin($email, false, 'User not found');
echo json_encode(['status' => 'error', 'message' => 'User with that email does not exist.']);
}