| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- <?php
- namespace Middlewares;
- use Firebase\JWT\JWT;
- use Firebase\JWT\Key;
- use Libs\Database;
- use Libs\Logger;
- use Libs\Payload;
- use Psr\Http\Message\ServerRequestInterface;
- class JwtAuthMiddleware
- {
- private string $jwtSecret;
- public function __construct()
- {
- // Sem fallback: a chave precisa estar configurada no ambiente.
- $this->jwtSecret = $_ENV['JWT_SECRET'] ?? '';
- }
- public function __invoke(ServerRequestInterface $request, callable $next)
- {
- if ($this->jwtSecret === '') {
- // Configuração ausente é erro de servidor, não de autenticação.
- Logger::error('JWT_SECRET is not configured; rejecting authenticated request');
- return Payload::fail('Internal server error', [], 'E_GENERIC', 500);
- }
- $authHeader = $request->getHeaderLine('Authorization');
- if (empty($authHeader) || !preg_match('/Bearer\s+(.*)/', $authHeader, $matches)) {
- return Payload::fail('Unauthorized', [], 'E_VALIDATE', 401);
- }
- $token = $matches[1];
- try {
- $decoded = JWT::decode($token, new Key($this->jwtSecret, 'HS256'));
- $userId = $decoded->sub ?? null;
- $userEmail = $decoded->email ?? $decoded->username ?? null;
- if (empty($userId) || empty($userEmail)) {
- return Payload::fail('Unauthorized', [], 'E_VALIDATE', 401);
- }
- $pdo = Database::pdo();
- // O papel (role) é lido do banco — fonte autoritativa — e não do JWT.
- // Assim, alterar/revogar o papel de um usuário tem efeito imediato,
- // mesmo que ele ainda possua um token antigo válido.
- $stmt = $pdo->prepare("SELECT user_id, user_email, user_role FROM \"user\" WHERE user_id = :user_id AND user_email = :user_email AND user_deleted_at = 'infinity'");
- $stmt->execute(['user_id' => $userId, 'user_email' => mb_strtolower(trim($userEmail))]);
- $user = $stmt->fetch(\PDO::FETCH_ASSOC);
- if (!$user) {
- return Payload::fail('Unauthorized', [], 'E_VALIDATE', 401);
- }
- $request = $request
- ->withAttribute('api_user', $user['user_email'])
- ->withAttribute('api_user_id', $user['user_id'])
- ->withAttribute('user_email', $user['user_email'])
- ->withAttribute('user_id', $user['user_id'])
- ->withAttribute('user_role', $user['user_role']);
- return $next($request);
- } catch (\Exception $e) {
- // Detalhe do erro vai só para o log; cliente recebe mensagem genérica.
- Logger::warning('JWT authentication failed', ['error' => $e->getMessage()]);
- return Payload::fail('Unauthorized', [], 'E_VALIDATE', 401);
- }
- }
- }
|