secret = $secret ?? $_ENV['JWT_SECRET'] ?? getenv('JWT_SECRET') ?: ''; if (empty($this->secret)) { throw new RuntimeException('JWT secret is not configured.'); } $this->expiresIn = $expiresIn ?? (int)($_ENV['JWT_EXPIRES_IN'] ?? getenv('JWT_EXPIRES_IN') ?: 86400); } /** * Gera um novo token JWT para o payload fornecido. * * @param array $userData Dados do usuário e contexto * @return array{token: string, expires_in: int, expires_at: int} */ public function generateToken(array $userData): array { $now = time(); $expiresAt = $now + $this->expiresIn; $payload = array_merge($userData, [ 'iat' => $now, 'nbf' => $now, 'exp' => $expiresAt, ]); $token = JWT::encode($payload, $this->secret, 'HS256'); return [ 'token' => $token, 'expires_in' => $this->expiresIn, 'expires_at' => $expiresAt, ]; } /** * Decodifica e valida o token JWT. * Retorna o payload em array ou lança uma exceção caso inválido ou expirado. * * @param string $token * @return array * @throws RuntimeException */ public function validateToken(string $token): array { try { $decoded = JWT::decode($token, new Key($this->secret, 'HS256')); return (array)$decoded; } catch (Throwable $e) { throw new RuntimeException('Token inválido ou expirado: ' . $e->getMessage(), 401, $e); } } }