Guias JWT

Claim exp do JWT: Como Funciona a Expiração

Entenda o claim exp do JWT, NumericDate, segundos versus milissegundos, clock skew e como confirmar se a expiração realmente está causando o erro.

Por JWTDecoder.toolsÚltima verificação em 2026-09-12

Voz editorial: a primeira pessoa descreve o fluxo de trabalho documentado do JWTDecoder.tools; JWTDecoder.tools é o editor e autor organizacional.

Linha do tempo JWT com iat, nbf, janela ativa e exp
Comparo iat, nbf, janela ativa e exp antes de concluir que o problema é expiração.

Quando vejo token expired, jwt expired ou um 401 que pode estar ligado ao tempo, o primeiro claim que normalmente verifico é exp. Não assumo que a mensagem da biblioteca explica tudo. Eu decodifico o token, converto o timestamp, comparo com o relógio do serviço que rejeitou a requisição e só então concluo se a expiração é a causa.

Para uma resposta rápida, uso o Verificador de Expiração JWT, que transforma exp, iat e nbf em horários UTC legíveis.

O que exp significa

A RFC 7519 define exp como Expiration Time. O valor é um NumericDate medido em segundos desde o Unix epoch.

Um payload pode conter:

{
  "sub": "user_123",
  "iat": 1789200000,
  "exp": 1789203600
}

Leio iat como o horário de emissão declarado e exp como o instante a partir do qual o token não deve mais ser aceito.

A comparação conceitual é:

horário atual do verificador >= exp

Quando isso se torna verdadeiro, um verificador que aplica expiração deve rejeitar o token.

O erro mais comum: segundos versus milissegundos

JWT NumericDate usa segundos. JavaScript Date.now() usa milissegundos.

Então espero código como:

const expiresAt = payload.exp * 1000;
const expired = Date.now() >= expiresAt;

Se encontro Date.now() sendo comparado diretamente com um exp normal de 10 dígitos, as unidades estão erradas.

Esse erro também aparece quando alguém gera exp com Date.now() sem dividir por 1000, criando um timestamp absurdamente distante no futuro.

Como confirmo se o token realmente expirou

Uso esta sequência:

  1. Decodifico o token e confirmo que exp existe.
  2. Converto exp para UTC.
  3. Comparo com o relógio do serviço que rejeitou o token.
  4. Verifico nbf e iat no mesmo contexto.
  5. Confiro se o verificador aplica tolerância de relógio.

O passo 3 é essencial. O relógio do meu notebook não é necessariamente o relógio usado pela API, gateway ou biblioteca de autenticação.

Como penso sobre clock skew

A RFC 7519 permite uma pequena margem para diferenças de relógio entre sistemas.

Quando um token parece expirar alguns segundos antes do esperado, verifico:

  • o relógio da API está sincronizado?
  • o relógio do provedor de identidade está sincronizado?
  • a biblioteca tem uma configuração explícita de tolerância?

Não aumento a tolerância para vários minutos apenas para fazer o erro desaparecer. Isso amplia a janela efetiva de aceitação além do valor declarado pelo emissor.

Se a diferença é de poucos segundos na fronteira, clock skew é plausível. Se o token expirou há uma hora, clock skew não é uma boa explicação.

O que faço quando exp não existe

A ausência de exp não torna todo JWT malformado automaticamente.

A especificação base define o claim, mas perfis e aplicações decidem quais claims são obrigatórios. Para um access token que deveria ser de curta duração, a ausência de exp merece investigação. Para outro tipo de JWT, a política pode ser diferente.

O Validador JWT sinaliza a ausência sem fingir que todos os perfis JWT possuem regras idênticas.

Um token não expirado ainda pode falhar

Se exp está no futuro, sigo adiante. Um JWT ativo no tempo ainda pode falhar porque:

  • a assinatura não verifica;
  • nbf está no futuro;
  • iss não corresponde ao emissor confiável;
  • aud aponta para outra API;
  • o token veio de outro ambiente;
  • o tipo de token está errado;
  • scopes ou roles necessários estão ausentes.

Quando a linha do tempo parece correta, uso o Depurador JWT para comparar emissor e audiência e o Verificador de Assinatura JWT quando tenho material de chave confiável.

Por que não edito exp para renovar um token

Se um JWT assinado expirou, não altero o payload esperando que a assinatura antiga continue válida.

Trocar:

{
  "exp": 1789203600
}

por um valor maior modifica os bytes assinados. Sem a credencial legítima de assinatura, o token alterado deve falhar na verificação.

A correção normal é obter um novo token pelo fluxo de refresh ou autenticação definido pelo sistema.

Como leio iat, nbf e exp juntos

Raramente olho exp isoladamente. Penso na linha do tempo:

emitido -------- janela ativa -------- expirado
  iat      nbf                       exp

Pergunto:

  • iat faz sentido para o momento em que o login ocorreu?
  • nbf está depois do relógio atual do verificador?
  • exp vem depois de iat?
  • a validade declarada parece curta ou longa demais?

Uma linha do tempo estranha pode revelar erro de unidade, relógio incorreto, token de outro ambiente ou regra específica do perfil.

Meu fluxo prático para problemas de expiração

Quando suspeito de exp, sigo esta ordem:

  1. Abro o Verificador de Expiração JWT.
  2. Confirmo que exp está em segundos, não milissegundos.
  3. Comparo a data UTC com o relógio do serviço que rejeitou a requisição.
  4. Inspeciono iat e nbf em busca de contradições.
  5. Verifico a tolerância de relógio configurada.
  6. Se o token realmente expirou, obtenho outro pelo fluxo legítimo.
  7. Se ainda está ativo, verifico assinatura, emissor e audiência.

exp é um sinal de diagnóstico muito útil, mas não é um veredito completo. Ele responde “o token está fora da janela temporal declarada?”, não “esta aplicação deve confiar e aceitar este JWT?”

Fontes e referências

Guias relacionados