JWTAuthMiddleware.php 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. <?php
  2. namespace Middlewares;
  3. use Firebase\JWT\JWT;
  4. use Firebase\JWT\Key;
  5. use Libs\ResponseLib;
  6. use Psr\Http\Message\ServerRequestInterface;
  7. use React\Http\Message\Response;
  8. class JwtAuthMiddleware
  9. {
  10. private string $jwtSecret;
  11. public function __construct()
  12. {
  13. // Carrega a chave secreta do .env (ex: JWT_SECRET=seu-segredo-aqui)
  14. $this->jwtSecret = $_ENV['JWT_SECRET'] ?? 'default-secret-fallback'; // Use um fallback seguro em dev
  15. }
  16. public function __invoke(ServerRequestInterface $request, callable $next)
  17. {
  18. // 1. Extrai o token do header Authorization
  19. $authHeader = $request->getHeaderLine('Authorization');
  20. if (empty($authHeader) || !preg_match('/Bearer\s+(.*)/', $authHeader, $matches)) {
  21. return ResponseLib::sendFail("Unauthorized: Missing or invalid Authorization header", [], "E_VALIDATE")->withStatus(401);
  22. }
  23. $token = $matches[1];
  24. try {
  25. // 2. Decodifica e valida o JWT
  26. $decoded = JWT::decode($token, new Key($this->jwtSecret, 'HS256')); // Use HS256 ou algoritmo desejado
  27. // 3. Extrai claims (assuma que o JWT tem 'sub' como user_id e 'username')
  28. $userId = $decoded->sub ?? null;
  29. $apiUser = $decoded->username ?? null;
  30. if (empty($userId) || empty($apiUser)) {
  31. return ResponseLib::sendFail("Unauthorized: Invalid JWT claims", [], "E_VALIDATE")->withStatus(401);
  32. }
  33. // 4. Verifica se o usuário existe e está ativo no banco (similar ao HMAC)
  34. $dbFile = $_ENV['DB_FILE'] ?? 'bridge.db';
  35. $dbPath = __DIR__ . '/../' . $dbFile;
  36. $pdo = new \PDO("sqlite:" . $dbPath);
  37. $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
  38. $pdo->setAttribute(\PDO::ATTR_TIMEOUT, 5000);
  39. $stmt = $pdo->prepare("SELECT user_id FROM user WHERE user_id = :user_id AND user_name = :user_name AND user_flag = 'a'");
  40. $stmt->execute(['user_id' => $userId, 'user_name' => $apiUser]);
  41. $user = $stmt->fetch(\PDO::FETCH_ASSOC);
  42. $stmt->closeCursor();
  43. if (!$user) {
  44. return ResponseLib::sendFail("Unauthorized: Invalid or inactive user", [], "E_VALIDATE")->withStatus(401);
  45. }
  46. // 5. Tudo certo, adiciona atributos ao request (compatível com HMAC)
  47. $request = $request
  48. ->withAttribute('api_user', $apiUser)
  49. ->withAttribute('api_user_id', $userId);
  50. return $next($request);
  51. } catch (\Exception $e) {
  52. // Captura erros de JWT (ex: expirado, inválido)
  53. return ResponseLib::sendFail("Unauthorized: " . $e->getMessage(), [], "E_VALIDATE")->withStatus(401);
  54. }
  55. }
  56. }