Mensagem de erro
jwt expired
O que significa
O TokenExpiredError do jsonwebtoken: a claim exp do token (um timestamp Unix em segundos) é anterior à hora atual do relógio do verificador. A assinatura em si pode ser perfeitamente válida — o token simplesmente ultrapassou o tempo de vida que o emissor lhe deu. O objeto de erro traz expiredAt com o momento exato.
Por que acontece
O token realmente expirou
comumTokens de acesso de curta duração (de 5 a 60 minutos) são a norma; um cliente que guarda um token em cache e o reutiliza depois, ou um job em segundo plano que mantém um token durante uma execução longa, vai encontrar este erro exatamente no horário previsto. A correção é um fluxo de renovação, não um tempo de vida maior.
Diferença de relógio entre o emissor e o verificador
comumSe o relógio do servidor que faz a verificação estiver adiantado em relação ao do emissor, os tokens “expiram” antes da hora — às vezes no exato momento em que são emitidos. O relógio de contêineres e VMs sem NTP se desajusta surpreendentemente rápido; uma diferença de dois minutos basta para quebrar de forma intermitente tokens que duram menos de uma hora.
O exp foi gravado na unidade errada
ocasionalA especificação (RFC 7519) define o exp em segundos. Um código que divide por 1000 uma vez a mais gera timestamps em 1970, e todo token já nasce expirado. O deslize oposto — Date.now() (milissegundos) gravado em exp — nem dispara este erro: ele gera timestamps mais de 56.000 anos no futuro, e o token nunca expira.
Como corrigir
- 1.
Permitir explicitamente uma pequena diferença de relógio
A opção clockTolerance aceita segundos e se aplica a exp e a nbf. Mantenha o valor pequeno (30–60 s) — ele existe para absorver o desvio dos relógios, não para estender o tempo de vida dos tokens.
js jwt.verify(token, publicKey, { algorithms: ["ES256"], clockTolerance: 30, // seconds of tolerated skew }); - 2.
Inspecionar o exp antes de culpar o relógio
Decodifique as claims e imprima o exp ao lado da hora atual. Se o exp parecer 1.7e12, você tem um bug de milissegundos; se estiver alguns minutos no passado, você precisa de lógica de renovação.
js const { exp } = jwt.decode(token); console.log("exp:", new Date(exp * 1000).toISOString()); console.log("now:", new Date().toISOString()); - 3.
Sincronizar os relógios e adicionar um caminho de renovação
Rode o NTP (chrony/systemd-timesyncd) nos hosts que fazem a verificação e implemente a renovação do token no lado do cliente ao receber respostas 401. Nunca leve ignoreExpiration: true para produção — isso transforma qualquer token vazado em uma credencial permanente.