JwtAuthMiddleware.php 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. <?php
  2. namespace Middlewares;
  3. use Firebase\JWT\JWT;
  4. use Firebase\JWT\Key;
  5. use Libs\Database;
  6. use Libs\Logger;
  7. use Libs\Payload;
  8. use Psr\Http\Message\ServerRequestInterface;
  9. class JwtAuthMiddleware
  10. {
  11. private string $jwtSecret;
  12. public function __construct()
  13. {
  14. // Sem fallback: a chave precisa estar configurada no ambiente.
  15. $this->jwtSecret = $_ENV['JWT_SECRET'] ?? '';
  16. }
  17. public function __invoke(ServerRequestInterface $request, callable $next)
  18. {
  19. if ($this->jwtSecret === '') {
  20. // Configuração ausente é erro de servidor, não de autenticação.
  21. Logger::error('JWT_SECRET is not configured; rejecting authenticated request');
  22. return Payload::fail('Internal server error', [], 'E_GENERIC', 500);
  23. }
  24. $authHeader = $request->getHeaderLine('Authorization');
  25. if (empty($authHeader) || !preg_match('/Bearer\s+(.*)/', $authHeader, $matches)) {
  26. return Payload::fail('Unauthorized', [], 'E_VALIDATE', 401);
  27. }
  28. $token = $matches[1];
  29. try {
  30. $decoded = JWT::decode($token, new Key($this->jwtSecret, 'HS256'));
  31. $userId = $decoded->sub ?? null;
  32. $userEmail = $decoded->email ?? $decoded->username ?? null;
  33. if (empty($userId) || empty($userEmail)) {
  34. return Payload::fail('Unauthorized', [], 'E_VALIDATE', 401);
  35. }
  36. $pdo = Database::pdo();
  37. $stmt = $pdo->prepare("SELECT user_id, user_email FROM \"user\" WHERE user_id = :user_id AND user_email = :user_email AND user_deleted_at = 'infinity'");
  38. $stmt->execute(['user_id' => $userId, 'user_email' => mb_strtolower(trim($userEmail))]);
  39. $user = $stmt->fetch(\PDO::FETCH_ASSOC);
  40. if (!$user) {
  41. return Payload::fail('Unauthorized', [], 'E_VALIDATE', 401);
  42. }
  43. $request = $request
  44. ->withAttribute('api_user', $user['user_email'])
  45. ->withAttribute('api_user_id', $user['user_id'])
  46. ->withAttribute('user_email', $user['user_email'])
  47. ->withAttribute('user_id', $user['user_id']);
  48. return $next($request);
  49. } catch (\Exception $e) {
  50. // Detalhe do erro vai só para o log; cliente recebe mensagem genérica.
  51. Logger::warning('JWT authentication failed', ['error' => $e->getMessage()]);
  52. return Payload::fail('Unauthorized', [], 'E_VALIDATE', 401);
  53. }
  54. }
  55. }