auth.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <?php
  2. /**
  3. * Authentication and Authorization Middleware
  4. * Handles user authentication and role-based access control
  5. */
  6. class AuthMiddleware {
  7. private $db;
  8. private $user;
  9. public function __construct($db) {
  10. $this->db = $db;
  11. require_once __DIR__ . '/../models/User.php';
  12. $this->user = new User($db);
  13. }
  14. /**
  15. * Authenticate user from JWT token or session
  16. * @return array|null User data or null if not authenticated
  17. */
  18. public function authenticate() {
  19. // Check for Authorization header
  20. $headers = getallheaders();
  21. $auth_header = $headers['Authorization'] ?? $headers['authorization'] ?? '';
  22. if ($auth_header) {
  23. // Extract token from "Bearer <token>" format
  24. $token = str_replace('Bearer ', '', $auth_header);
  25. return $this->validateToken($token);
  26. }
  27. // Fallback to session-based authentication
  28. if (session_status() === PHP_SESSION_NONE) {
  29. session_start();
  30. }
  31. if (isset($_SESSION['user_id'])) {
  32. $this->user->id = $_SESSION['user_id'];
  33. $this->user->readOne();
  34. if ($this->user->username) {
  35. return [
  36. 'id' => $this->user->id,
  37. 'username' => $this->user->username,
  38. 'email' => $this->user->email,
  39. 'first_name' => $this->user->first_name,
  40. 'last_name' => $this->user->last_name,
  41. 'role' => $this->user->role,
  42. 'is_active' => $this->user->is_active
  43. ];
  44. }
  45. }
  46. return null;
  47. }
  48. /**
  49. * Validate JWT token (simplified implementation)
  50. * @param string $token JWT token
  51. * @return array|null User data or null if invalid
  52. */
  53. private function validateToken($token) {
  54. // For now, implement a simple token validation
  55. // In production, use a proper JWT library
  56. try {
  57. $payload = json_decode(base64_decode($token), true);
  58. if (isset($payload['user_id']) && isset($payload['expires'])) {
  59. if ($payload['expires'] > time()) {
  60. $this->user->id = $payload['user_id'];
  61. $this->user->readOne();
  62. if ($this->user->username && $this->user->is_active) {
  63. return [
  64. 'id' => $this->user->id,
  65. 'username' => $this->user->username,
  66. 'email' => $this->user->email,
  67. 'first_name' => $this->user->first_name,
  68. 'last_name' => $this->user->last_name,
  69. 'role' => $this->user->role,
  70. 'is_active' => $this->user->is_active
  71. ];
  72. }
  73. }
  74. }
  75. } catch (Exception $e) {
  76. // Token is invalid
  77. }
  78. return null;
  79. }
  80. /**
  81. * Check if user has admin role
  82. * @param array $user User data
  83. * @return bool True if user is admin
  84. */
  85. public function isAdmin($user) {
  86. return $user && $user['role'] === 'admin';
  87. }
  88. /**
  89. * Check if user can access resource
  90. * @param array $user User data
  91. * @param string $required_role Required role (admin/user)
  92. * @param int|null $resource_owner_id Resource owner ID (for profile access)
  93. * @return bool True if user can access
  94. */
  95. public function canAccess($user, $required_role = null, $resource_owner_id = null) {
  96. if (!$user || !$user['is_active']) {
  97. return false;
  98. }
  99. // Admin can access everything
  100. if ($user['role'] === 'admin') {
  101. return true;
  102. }
  103. // Check if specific role is required
  104. if ($required_role && $user['role'] !== $required_role) {
  105. return false;
  106. }
  107. // Check if user is accessing their own resource (profile management)
  108. if ($resource_owner_id && $user['id'] == $resource_owner_id) {
  109. return true;
  110. }
  111. // Default: allow access for regular users to their own resources
  112. return !$resource_owner_id;
  113. }
  114. /**
  115. * Generate simple JWT token
  116. * @param array $user User data
  117. * @return string JWT token
  118. */
  119. public function generateToken($user) {
  120. $payload = [
  121. 'user_id' => $user['id'],
  122. 'username' => $user['username'],
  123. 'role' => $user['role'],
  124. 'expires' => time() + (24 * 60 * 60) // 24 hours
  125. ];
  126. return base64_encode(json_encode($payload));
  127. }
  128. /**
  129. * Send unauthorized response
  130. */
  131. public function sendUnauthorizedResponse() {
  132. http_response_code(401);
  133. echo json_encode([
  134. 'success' => false,
  135. 'message' => 'Unauthorized access. Please login.'
  136. ]);
  137. exit;
  138. }
  139. /**
  140. * Send forbidden response
  141. */
  142. public function sendForbiddenResponse() {
  143. http_response_code(403);
  144. echo json_encode([
  145. 'success' => false,
  146. 'message' => 'Access denied. Insufficient permissions.'
  147. ]);
  148. exit;
  149. }
  150. }
  151. ?>