Entenda os claims de tokens JWT incluindo exp, iat, nbf, iss, sub, aud. Cobrança de skew de relógio, padrões de renovação de tokens e erros comuns.
Um JWT são três segmentos codificados em base64url separados por pontos: header.payload.signature. O payload contém claims, que são pares chave-valor que carregam dados de identidade e autorização. Cada claim é visível para qualquer pessoa que tenha o token. Não há criptografia, apenas uma assinatura que verifica que o token foi emitido por uma parte confiável.
Os claims se dividem em três categorias:
iss, sub, aud, exp, nbf, iat e jti.role, org_id, permissions).Esses três claims formam o ciclo de vida de um token:
iat ──────────── nbf ──────────── token ativo ──────────── exp
│ │
└── token começa a ser válido └── token expira
iat (Emitido Em)
O timestamp Unix quando o token foi criado. É informativo. Não afeta a validação a menos que a lógica da sua aplicação o use para impor uma idade máxima do token.
{
"iat": 1735603200
}
1735603200 = 1 de janeiro de 2025 às 00:00:00 UTC.
nbf (Não Antes)
O timestamp Unix quando o token se torna válido. Se um token chega com um nbf no futuro, o servidor deve rejeitá-lo. Isso é raro na prática. A maioria dos sistemas define nbf igual a iat.
{
"nbf": 1735603200
}
exp (Expiração)
O timestamp Unix quando o token se torna inválido. Este é o claim de tempo chave. O servidor deve rejeitar qualquer token com exp no passado.
{
"exp": 1735689600,
"iat": 1735603200
}
A diferença é 86400 segundos (24 horas). Este token tem uma vida útil de um dia.
Além dos claims de tempo, a spec JWT define vários claims padrão:
| Claim | Nome | Propósito | Exemplo |
|---|---|---|---|
iss |
Emissor | Quem criou o token | "https://api.example.com" |
sub |
Sujeito | Quem o token representa | "user_12345" |
aud |
Audiência | Para quem o token é | "https://app.example.com" |
exp |
Expiração | Quando o token expira | 1735689600 |
nbf |
Não Antes | Quando o token se torna válido | 1735603200 |
iat |
Emitido Em | Quando o token foi criado | 1735603200 |
jti |
ID JWT | Identificador único do token | "abc-123-def" |
iss (Emissor): Identifica quem criou o token. Seu servidor de auth deve validar isso para impedir que tokens de outros emissores sejam aceitos.
sub (Sujeito): A entidade que o token representa. Tipicamente um ID de usuário ou nome de conta de serviço. Use isso na sua lógica de autorização para identificar quem está fazendo a requisição.
aud (Audiência): Para quem o token foi emitido. Se seu sistema tem múltiplos serviços (ex. API gateway, serviço de usuário, serviço de pagamento), cada um deve verificar que o claim aud corresponde ao seu próprio identificador.
jti (ID JWT): Um identificador único para o token. Use isso para revogação de tokens. Armazene o jti em uma lista de negação quando o usuário faz logout ou o token é revogado.
Os relógios dos servidores nunca estão perfeitamente sincronizados. Se o relógio do servidor de auth está 30 segundos à frente do servidor de API, um token com exp = 1735689600 pode ser validado contra um servidor que acha que já são 1735689631.
A solução é uma janela de tolerância:
// Node.js com jsonwebtoken
jwt.verify(token, secret, { clockTolerance: 30 }); // 30 segundos de tolerância
// Go com golang-jwt
token, err := jwt.Parse(tokenString, keyFunc,
jwt.WithLeeway(30 * time.Second),
)
Uma tolerância de 30-60 segundos é padrão. Não defina como zero ou você verá erros 401 intermitentes difíceis de depurar.
Usar exp com segundos vs milissegundos
Algumas bibliotecas usam segundos (padrão RFC 7519), outras milissegundos. Um token com exp: 1735689600 (segundos) parece ano 56935 se interpretado como milissegundos. Verifique a expectativa da sua biblioteca.
Definir exp longe demais no futuro
Um token com vida útil de 30 dias significa que um token roubado é usável por 30 dias. Os access tokens devem expirar em 15-60 minutos.
Validação aud faltando
Se sua API não verifica o claim aud, um token emitido para um serviço diferente pode ser usado contra seu endpoint. Sempre valide iss e aud.
Armazenar dados sensíveis nos claims
Os claims são legíveis por qualquer pessoa com o token. Não coloque senhas, SSN ou chaves privadas em claims JWT.
Cole o token de exemplo no JWT Decoder para ver todos os claims decodificados. O payload contém:
{
"iss": "https://api.example.com",
"sub": "user_12345",
"aud": "https://app.example.com",
"exp": 1735689600,
"iat": 1735603200,
"nbf": 1735603200,
"role": "admin",
"permissions": ["read", "write", "delete"]
}
O token foi emitido à meia-noite UTC em 1 de janeiro de 2025, expira 24 horas depois e concede acesso de admin a user_12345.
Nothing you paste leaves this tab. Every tool runs entirely in your browser — no upload, no server, no account.