Toda vez que um usuário faz login em uma aplicação SaaS, um
token de autenticação
é gerado e enviado para o navegador ou aplicativo móvel dele. Esse token carrega um relógio silencioso dentro de si. O campo de
expiração do JWT, armazenado como um timestamp Unix simples, indica a qualquer servidor que o leia exatamente quando parar de confiar naquela credencial. Errar esse timestamp por apenas alguns segundos pode fazer com que usuários sejam desconectados cedo demais ou, pior, que carreguem uma sessão válida por muito mais tempo do que sua política de segurança permite. Entender como as claims de um
JSON web token
funcionam, especialmente
exp
e
iat
, é uma das coisas mais práticas que uma equipe SaaS pode fazer para reforçar a autenticação sem criar atrito para o usuário.
Principais pontos:
-
As claims
expeiatem um JWT JSON web token são sempre timestamps Unix medidos em segundos inteiros, não em milissegundos. - A diferença de relógio entre servidores pode invalidar tokens silenciosamente ou estender sessões além do permitido pela política - uma tolerância de 60 segundos é a solução padrão do mercado.
- Definir a expiração do token por muito tempo aumenta o risco em caso de comprometimento; defini-la por muito pouco prejudica a experiência do usuário. Uma fórmula objetiva ajuda a escolher o valor certo.
- Você pode decodificar e verificar qualquer timestamp de um JSON web token em segundos usando um conversor de época Unix, sem precisar de nenhuma biblioteca.
Índice
- O que é um JWT e por que timestamps vivem dentro dele
-
As claims
expeiatexplicadas - Um exemplo concreto: decodificando timestamps reais de tokens
- Clock skew: o inimigo silencioso dos tokens
- Escolhendo a expiração de token certa para o seu produto SaaS
- Passos práticos para implementar a expiração segura de JWT
- Conclusão
O que é um JWT e por que timestamps vivem dentro dele
Um JSON web token é uma credencial compacta e segura para URLs, composta por três partes codificadas em Base64 separadas por pontos: um header, um payload e uma assinatura. O payload é onde os dados sensíveis ao tempo ficam armazenados. Como JWTs são stateless, o servidor não consulta uma sessão em banco de dados para validá-los. Em vez disso, ele lê as claims embutidas no payload e confia na assinatura criptográfica. Esse design é rápido e escalável, mas cria uma limitação real: depois que um token é emitido, o servidor não pode "deletá-lo". A única forma confiável de limitar seu tempo de vida é incorporar um timestamp de expiração diretamente no próprio token.
É por isso que o tempo, especificamente o tempo de época Unix, é central para a segurança do JWT. A especificação RFC 7519 que define os JWTs exige que as claims relacionadas ao tempo sejam expressas como valores "NumericDate", que são simplesmente o número de segundos desde 1º de janeiro de 1970 UTC. Sem fusos horários. Sem formatação regional. Apenas um inteiro que qualquer servidor em qualquer lugar do mundo pode comparar com seu próprio relógio.
As claims
exp
e
iat
explicadas
A especificação JWT define diversas claims registradas. Duas são as mais importantes para o gerenciamento do ciclo de vida do token:
-
exp(Expiration Time): O timestamp após o qual o token não deve mais ser aceito. Os servidores são obrigados a rejeitar qualquer token em que o horário atual seja igual ou superior a esse valor. Esse é o mecanismo central por trás da expiração do JWT. -
iat(Issued At): O timestamp no momento em que o token foi criado. A claim iat não é validada por padrão, mas é extremamente útil. Ela permite calcular a idade de um token, aplicar uma política de idade máxima independentemente doexp, e detectar tokens emitidos de forma suspeita no passado distante.
Uma terceira claim,
nbf
(Not Before), define o horário mais cedo em que um token é válido. É menos utilizada, mas segue o mesmo formato de timestamp Unix.
Os três valores são inteiros. Se o seu sistema os gera em milissegundos (um erro comum ao usar o
Date.now()
do JavaScript), o número resultante será aproximadamente 1.000 vezes maior do que o esperado. Um servidor que verifica o
exp
contra o segundo de época atual vai enxergar um token que aparentemente expira no ano 33.658 e jamais o rejeitará. Esse é um bug real de produção que já afetou diversas equipes SaaS.
Um exemplo concreto: decodificando timestamps reais de tokens
Suponha que seu serviço de autenticação emita o seguinte payload de JWT após um usuário fazer login às 10:00 UTC do dia 1º de julho de 2025:
{
"sub": "user_8821",
"iat": 1751364000,
"exp": 1751367600,
"role": "admin"
}
Veja o que esses números significam:
| Claim | Timestamp Unix | Legível por humanos (UTC) | Significado |
|---|---|---|---|
iat
|
1751364000 | 2025-07-01 10:00:00 | Token foi emitido neste momento |
exp
|
1751367600 | 2025-07-01 11:00:00 | Token expira exatamente 1 hora depois |
A diferença é exatamente 3.600 segundos, ou seja, uma hora. Qualquer servidor que receber esse token após as 11:00:00 UTC deve rejeitá-lo. Para verificar isso manualmente, basta subtrair
iat
de
exp
: 1751367600 - 1751364000 = 3600 segundos. Você pode confirmar o equivalente legível de qualquer um desses valores instantaneamente usando um conversor de timestamp Unix, que é exatamente o tipo de verificação rápida que evita o bug de milissegundos versus segundos mencionado anteriormente.
Para mais contexto sobre como bancos de dados devem armazenar esses valores, consulte nosso guia sobre
timestamps Unix em bancos de dados, já que o mesmo formato inteiro se aplica tanto ao armazenamento do
exp
em um token quanto em uma tabela de log de auditoria.
Clock skew: o inimigo silencioso dos tokens
Aqui está uma limitação real que pega muitas equipes de surpresa. Em um sistema distribuído, seu servidor de autenticação e seu servidor de API são máquinas diferentes. Os relógios do sistema delas são sincronizados via NTP, mas nunca estão perfeitamente alinhados. Uma diferença de 30 a 90 segundos é comum em ambientes de nuvem.
Considere este cenário: um token com
exp = 1751367600
é validado por um servidor de API cujo relógio marca 1751367610, apenas 10 segundos após a expiração. O token é rejeitado. O usuário recebe um erro 401. Da perspectiva dele, acabou de fazer login e o aplicativo simplesmente quebrou.
A solução padrão é incorporar uma tolerância de clock skew na sua lógica de validação. A maioria das bibliotecas JWT suporta um parâmetro de margem. Um valor de 60 segundos é amplamente aceito e está referenciado na especificação OpenID Connect Core. Configure esse valor, documente-o e certifique-se de que todos os serviços da sua stack usem o mesmo.
Regra prática:
Adicione uma margem de 60 segundos na validação do
exp
. Nunca adicione margem nas verificações do
iat
, pois isso permitiria aceitar tokens emitidos no futuro, o que é um sinal claro de ataques de replay.
Escolhendo a expiração de token certa para o seu produto SaaS
O valor ideal de expiração do token depende da sensibilidade da sua aplicação e do comportamento esperado da sessão. Veja um framework prático:
- Aplicações de alta sensibilidade (bancos, saúde, painéis administrativos): 15 a 30 minutos para access tokens. Use refresh tokens para renovar sessões de forma transparente.
- Aplicações SaaS padrão (gerenciamento de projetos, CRM, analytics): 1 a 8 horas. Alinhe com a duração típica de uma sessão de trabalho.
- APIs de baixo risco ou somente leitura: Até 24 horas, mas combine com rotação de tokens em ações sensíveis.
- Tokens de serviço machine-to-machine: Podem ser mais longos (dias ou semanas), mas devem ter escopo restrito e ser rotacionados periodicamente.
Uma fórmula útil para calcular o valor de
exp
no momento da emissão:
// Exemplo em Node.js
const iat = Math.floor(Date.now() / 1000); // horário atual em segundos
const ttl = 3600; // time-to-live: 1 hora em segundos
const exp = iat + ttl;
const payload = {
sub: userId,
iat: iat,
exp: exp
};
Observe a divisão explícita por 1000 para converter de milissegundos para segundos. Essa única linha previne o bug de timestamp mais comum em aplicações JavaScript com JWT.
Passos práticos para implementar a expiração segura de JWT
Veja um checklist concreto que você pode aplicar hoje em qualquer sistema de autenticação SaaS:
-
Sempre inclua tanto
iatquantoexp. A claimiaté tecnicamente opcional, mas fornece uma trilha de auditoria e permite aplicar uma política de idade máxima independente da expiração. -
Verifique o formato do timestamp antes de fazer o deploy.
Decodifique seu token e confira se o
expé um inteiro de 10 dígitos. Um valor de 13 dígitos significa que milissegundos entraram no cálculo. - Configure uma margem de clock skew de 60 segundos no seu middleware de validação. Aplique de forma consistente em todos os serviços que consomem tokens de autenticação.
- Use access tokens de curta duração combinados com refresh tokens. Um access token de 15 minutos combinado com um refresh token de 7 dias é muito mais seguro do que um único access token de 7 dias, pois o refresh token pode ser revogado no lado do servidor.
-
Registre o valor de
iatem cada requisição autenticada. Isso permite detectar anomalias, como o mesmo token sendo usado simultaneamente em duas regiões geográficas diferentes. -
Teste a expiração em staging com tempo acelerado.
Simule o relógio avançando além do valor de
expe confirme que sua aplicação lida com o erro 401 de forma elegante, sem travar ou entrar em loop.
Se você precisar converter rapidamente um valor bruto de
exp
de um token em uma data legível, ou verificar qual timestamp definir para uma determinada duração, o
conversor de época na nossa página inicial
resolve as duas direções instantaneamente, sem precisar escrever nenhum código.
Conclusão
A expiração de JWT não é um conceito complexo, mas é um daqueles pontos em que pequenos erros criam grandes brechas de segurança. As claims
exp
e
iat
são apenas inteiros, timestamps Unix contados em segundos a partir da época. Essa simplicidade é justamente sua força: qualquer servidor, em qualquer linguagem e em qualquer plataforma, pode comparar dois números sem ambiguidade. A habilidade real está em aplicá-los corretamente: escolher uma duração sensata para a
expiração do token, tratar o clock skew com uma janela de tolerância, e identificar o erro de milissegundos versus segundos antes que ele chegue à produção. Incorpore esses hábitos no seu pipeline de autenticação e sua implementação de
JSON web token
será ao mesmo tempo segura e fácil de manter.
Verifique timestamps de JWT instantaneamente - sem precisar de código
Cole qualquer timestamp Unix de um payload JWT e converta para uma data legível com um clique. Identifique erros de milissegundos versus segundos antes de chegar à produção.
Experimente nossa ferramenta gratuita →
exp
(Expiration Time) é o timestamp Unix após o qual o token é inválido e deve ser rejeitado.
iat
(Issued At) é o timestamp de quando o token foi criado. Os dois são inteiros em segundos. A claim
iat
é opcional, mas muito útil para auditoria e para aplicar políticas de idade máxima do token.
Timestamps Unix são inteiros independentes de fuso horário, o que os torna inequívocos em todos os servidores e regiões. Strings de data formatadas como "2025-07-01T10:00:00" podem ser interpretadas de forma errada dependendo das configurações de localidade ou fuso horário. Uma comparação entre inteiros também é mais rápida e menos propensa a erros do que o parsing de strings em sistemas de autenticação com alto volume de requisições.
Um token de longa duração permanece válido mesmo que a conta do usuário seja comprometida ou que as permissões dele sejam alteradas. Como JWTs são stateless, o servidor não pode revogá-los no meio do ciclo de vida. Se um invasor roubar um token com expiração de 30 dias, ele terá 30 dias de acesso. Janelas de expiração curtas combinadas com refresh tokens reduzem significativamente essa janela de risco.
Em JavaScript, sempre use
Math.floor(Date.now() / 1000)
ao gerar os valores de
iat
ou
exp
. O
Date.now()
bruto retorna milissegundos. Dividir por 1000 converte para o inteiro baseado em segundos que a especificação JWT exige. Verifique se o seu timestamp tem 10 dígitos, e não 13.
Clock skew é a pequena diferença de horário entre os relógios do sistema de dois servidores em um sistema distribuído. Mesmo uma diferença de 30 segundos pode fazer com que um token válido seja rejeitado, caso o relógio do servidor que valida esteja ligeiramente adiantado. A solução padrão é configurar uma margem de 60 segundos na sua biblioteca de validação JWT para absorver a deriva normal do NTP.