← Voltar ao Blog

Rotação de token de atualização JWT: padrão seguro para sistemas reais

Segurança do desenvolvedor28 de março de 2026·9 min de leitura
JWT refresh token rotation diagram

A maioria dos tutoriais JWT param em "usar um token de atualização para sessões de longa duração". Eles raramente explicam o que acontece quando o token de atualização é roubado. Um token de atualização estático — que nunca muda — dá ao invasor o mesmo acesso persistente que um cookie de sessão roubado. Pior ainda, não há como detectar o roubo.

Rotação de token de atualização resolve isso emitindo um novo token de atualização a cada uso. Se um token antigo for reproduzido, toda a sessão será revogada. Este artigo aborda o padrão de implementação usado por Auth0, Okta e outros provedores de identidade sérios.

Por que os tokens de atualização estática falham

Um token de atualização estático tem um valor fixo para todo o tempo de vida da sessão (geralmente mais de 30 dias). Problemas:

A solução é tratar cada token de atualização como de uso único.

O modelo de rotação

Etapa 1: Login — Crie uma família de tokens

Quando o usuário autenticar, gere um family_id (UUID) que agrupe todos os tokens nesta sessão:

{ family_id: "f47ac10b-58cc-4372-a567-0e02b2c3d479", user_id: "user_123", refresh_token_hash: sha256(refresh_token), created_at: "2026-03-28T10:00:00Z", expires_at: "2026-04-27T10:00:00Z", used: false
}

Armazene este registro no lado do servidor. Nunca armazene tokens de atualização em localStorage — use httpOnly cookies ou armazenamento nativo seguro.

Etapa 2: Atualização do token — Girar

Quando o cliente apresenta o token de atualização:

  1. Procure o hash do token no banco de dados
  2. Verifique se pertence a uma família ativa e não está marcado como used
  3. Marque como usado: verdadeiro
  4. Emitir um token de atualização new (novo valor aleatório, mesmo family_id)
  5. Emitir um novo token de acesso
  6. Armazene o novo hash do token de atualização

Etapa 3: detecção de repetição

Se um token de atualização marcado como usado: true for apresentado novamente, isso significa:

A resposta segura: revogar todos os tokens da família. Isso força o usuário a fazer login novamente. É melhor incomodar um usuário legítimo uma vez do que permitir que um invasor mantenha o acesso.

// Repetição detectada — opção nuclear
aguarde db.query ( 'DELETE FROM refresh_tokens WHERE family_id = $1', [famíliaId]
);

Esquema de banco de dados

Uma tabela de token de atualização mínima:

CREATE TABLE atualização_tokens ( id UUID CHAVE PRIMÁRIA PADRÃO gen_random_uuid(), family_id UUID NÃO NULO, user_id UUID NOT NULL REFERÊNCIAS usuários(id), token_hash TEXTO NÃO NULO ÚNICO, usado BOOLEAN PADRÃO FALSO, criado_em TIMESTAMPTZ DEFAULT agora(), expira_at TIMESTAMPTZ NÃO NULO, substituído_por REFERÊNCIAS UUID update_tokens(id)
); CRIAR ÍNDICE idx_refresh_family ON refrescante_tokens(family_id);
CRIAR ÍNDICE idx_refresh_user ON update_tokens(user_id);

A coluna replaced_by cria uma cadeia que você pode seguir para fins de auditoria.

Tratamento de solicitações simultâneas

Em aplicativos reais, várias chamadas de API podem acionar uma atualização simultaneamente. Se a Chamada A girar o token enquanto a Chamada B ainda tiver o antigo, a Chamada B acionará a detecção de repetição – desconectando o usuário inesperadamente.

Padrão do período de carência

Permitir que o token de atualização anterior permaneça válido por um curto período (5 a 10 segundos) após a rotação:

const GRACE_PERIOD_MS = 10_000; if (token.usado) { const decorrido = Date.now() - token.rotated_at; se (decorrido < GRACE_PERIOD_MS) { // Within grace period — return the already-issued new tokens return getLatestTokensForFamily(token.family_id); } // Outside grace period — replay attack await revokeFamily(token.family_id); throw new UnauthorizedError('token_replayed');
}

Monitoramento e Alertas

Rastreie estes sinais na produção:

Token de atualização vs token de acesso: referência rápida

PropriedadeToken de acessoToken de atualização
Vida útil5–15 minutos7–30 dias
FormatJWT (independente)String opaco (recomendado)
ArmazenamentoMemória (variável JS)httpSomente cookie
Enviado paraservidores APIApenas servidor de autenticação
RotaçãoNão necessárioA cada uso

Para bugs de validação de reivindicação de tempo que frequentemente interagem com fluxos de atualização, consulte JWT exp/iat/nbf bugs comuns.

FAQ

Como devo lidar com solicitações de atualização simultâneas?

Use um curto período de carência (5 a 10 segundos) onde o token de atualização anterior ainda seja aceito. Isso lida com condições de corrida quando várias chamadas de API acionam uma atualização simultaneamente. Após o período de carência, apenas o token mais recente será válido.

Os tokens de atualização devem ser JWT ou strings opacas?

Strings opacos são geralmente mais seguros para tokens de atualização. Os JWTs carregam dados de carga útil que aumentam a superfície de ataque, e os tokens de atualização não precisam ser independentes, pois o servidor sempre os procura no banco de dados de qualquer maneira.

Por quanto tempo as sessões de atualização devem durar?

7–30 dias é o normal. Aplicativos de alta segurança (bancos, saúde) devem durar de 1 a 7 dias. Os aplicativos de consumo podem durar até 90 dias com rotação. Sempre combine sessões longas com impressão digital do dispositivo e detecção de anomalias.

Ferramentas e artigos relacionados