HmacAuthMiddleware.php 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. <?php
  2. namespace Middlewares;
  3. use Libs\ResponseLib;
  4. use Models\ApiUserModel;
  5. use Psr\Http\Message\ServerRequestInterface;
  6. use React\Http\Message\Response;
  7. class HmacAuthMiddleware
  8. {
  9. private array $api_Key;
  10. public function __construct()
  11. {
  12. // Instancia a model e carrega as chaves API
  13. $apiUserModel = new ApiUserModel();
  14. $this->api_Key = $apiUserModel->getApiKeys();
  15. }
  16. public function __invoke(ServerRequestInterface $request, callable $next)
  17. {
  18. // 1. Extrai headers
  19. $signature = $request->getHeaderLine('x-signature');
  20. $apiUser = $request->getHeaderLine('x-user');
  21. $nonce = $request->getHeaderLine('x-nonce');
  22. if (empty($signature) || empty($apiUser) || empty($nonce)) {
  23. return ResponseLib::sendFail("Unauthorized: Missing signature or headers", [], "E_VALIDATE")->withStatus(401);
  24. }
  25. // 2. Verifica se nonce está dentro do intervalo
  26. $currentTime = time();
  27. if (abs($currentTime - (int) $nonce) > 2) {
  28. return ResponseLib::sendFail("Unauthorized: Invalid or expired nonce", [], "E_VALIDATE")->withStatus(401);
  29. }
  30. // 3. Verifica se o usuário é válido
  31. if (!isset($this->api_Key[$apiUser])) {
  32. return ResponseLib::sendFail("Unauthorized: Invalid API User", [], "E_VALIDATE")->withStatus(401);
  33. }
  34. $apiKey = $this->api_Key[$apiUser]['user_apikey'];
  35. $apiSecret = $this->api_Key[$apiUser]['user_apisecret'];
  36. $secret = $apiKey . "::" . $apiSecret;
  37. // 4. Monta mensagem para HMAC: <jsonBody>::<nonce>
  38. $rawBody = (string) $request->getBody();
  39. $message = $rawBody . "::" . $nonce;
  40. // 5. Calcula assinatura esperada
  41. $expectedSignature = hash_hmac('sha256', $message, $secret);
  42. // 6. Verifica assinatura
  43. if (!hash_equals($expectedSignature, $signature)) {
  44. return ResponseLib::sendFail("Unauthorized: Signature mismatch", [], "E_VALIDATE")->withStatus(401);
  45. }
  46. // 7. Tudo certo, adiciona atributos ao request e segue
  47. $request = $request
  48. ->withAttribute('api_user', $apiUser)
  49. ->withAttribute('api_user_id', $this->api_Key[$apiUser]['user_id']);
  50. return $next($request);
  51. }
  52. }