Decodificar um Token JWT Expirado
Decodificar um JWT expirado revela o mêsmo payload que um token válido. A estrutura do token não muda; o claim exp só contém um timêstamp Unix no passado. Issó é útil para depurar erros de autenticação, verificar quais claims foram emitidos e saber quando um token expirou sem acessar os logs do servidor.
Token Decodificado
O token neste exemplo se decodifica assim:
{
"header": {
"alg": "HS256",
"typ": "JWT"
},
"payload": {
"sub": "1234567890",
"name": "Alice",
"iat": 1600000000,
"exp": 1600003600,
"iss": "auth.example.com",
"aud": "api.example.com"
}
}
iat é 1600000000 (13 de setembro de 2020, 12:26:40 UTC). exp é 1600003600, exatamente uma hora depois. Ambos são timêstamps Unix em segundos. Este token expirou em setembro de 2020.
Claims de Tempo e Seus Significados
iat (issued at)
O timêstamp Unix em que o token foi emitido. Usado para detectar tokens emitidos antes de uma rotação de chaves ou uma mudança de senha do usuário. Alguns sistemas rejeitam tokens com iat anterior à última mudança de senha do usuário, mêsmo que tecnicamente não tenham expirado.
exp (expires at)
O timêstamp Unix após o qual o token deve ser rejeitado. Servidores verificam current_time > exp e retornam 401 se verdadeiro. A verificação é estrita: um token com exp == current_time já é considerado expirado na maioria das implementações.
nbf (not before)
Menos comum. O timêstamp Unix antes do qual o token não deve ser aceito. Útil quando você emite um token para usó futuro ou quando quer um período de espera antes que o token se ative após a emissão.
Relação entre os três
issued at (iat) --> valid from (nbf) --> valid until (exp)
Na prática, iat e nbf geralmente são o mêsmo valor, ou nbf é omitido. O par crítico para a maioria das implementações é iat e exp.
Fluxo de Refresh de Token
Quando um access token expira, o cliente deve:
- Detectar a resposta 401 (ou verificar a expiração no lado do cliente antes da requisição)
- Enviar o refresh token ao endpoint de tokens (
POST /oauth/tokenou similar) - Receber um novo access token (e às vezes um novo refresh token)
- Tentar novamente a requisição original com o novo access token
- Se o refresh token também expirou, redirecionar o usuário ao fluxo de login
Uma biblioteca cliente bem implementada lida com os passos 1 a 4 de forma transparente. Usuários nunca veem erros de expiração a menos que seu refresh token também tenha expirado.
async function fetchWithRefresh(url, options) {
let response = await fetch(url, {
...options,
headers: { Authorization: `Bearer ${getAccessToken()}` }
});
if (response.status === 401) {
await refreshAccessToken();
response = await fetch(url, {
...options,
headers: { Authorization: `Bearer ${getAccessToken()}` }
});
}
return response;
}
Clock Skew
A expiração JWT compara o claim exp com o relógio atual do servidor. Se o servidor que emitiu o token é o servidor que o válida têm relógios que diferem por mais de alguns segundos, tokens válidos podem ser rejeitados imediatamente.
A tolerância padrão é uma margem de 5 minutos (exp + 300 > current_time). A maioria das bibliotecas JWT suporta uma tolerância de clock skew configurável. Sistemas de produção devem executar NTP ou um protocolo de sincronização de tempo similar para manter os relógios dos servidores dentro de alguns segundos um do outro.
Cenários Comuns de Depuração
Token expirou entre a emissão é o primeiro usó
O cliente recebeu um token mas não o usou imediatamente. Issó acontece em jobs em lote, tarefas em fila ou clientes com cache agressivo. Se a vida útil do seu access token é 1 hora é um job em background fica em uma fila por 90 minutos antes de executar, seu token estará expirado no primeiro uso. Soluções: busque um token fresco imediatamente antes da requisição, ou use uma conta de serviço com tokens de vida útil mais longa para jobs em background.
Clock drift do servidor
O relógio do servidor emissor está adiantado em relação ao servidor válidador. Um token emitido no tempo T com expiração de 5 minutos é válido até T+5m pelo relógio do emissor. Se o relógio do válidador está 10 minutos atrasado, ele vê o token como válido até T+5m+10m. Se o relógio do válidador está 10 minutos adiantado, ele rejeita o token imediatamente após a emissão. Monitore clock drift em todos os servidores que emitem ou válidam JWTs.
Confusão de fusó horário
Os claims exp e iat são sempre timêstamps Unix em segundos UTC. Não são strings de data formatadas. A confusão acontece quando desenvolvedores registram esses valores e os interpretam como hora local, ou quando constroem JWTs manualmente usando hora local em vez de epoch UTC. Para converter um valor exp para uma hora legível: new Date(exp * 1000).toISOString() em JavaScript, ou datetime.fromtimêstamp(exp, tz=timezone.utc) em Python.
Depuração com o decodificador de token
Cole qualquer JWT, mêsmo um expirado, para ver o valor exato de exp. Use o conversor de timêstamp Unix para converter para uma data legível. Compare com o iat para ver a vida útil pretendida do token e com o horário atual para ver há quanto tempo expirou.