Pular para o conteúdo

Fluxo de autenticação JWT: tokens de acesso, tokens de atualização e revogação

Como a autenticação JWT funciona de ponta a ponta: emitir e validar tokens de acesso, rotacionar refresh tokens, guardar tokens no navegador e revogá-los antes do prazo.

· Fundador e desenvolvedor

Publicado em

Diagrama de sequência com três linhas de vida: app de navegador, servidor de autorização e API de pedidos. O login devolve um token de acesso e um refresh token. O app chama a API com um token bearer. Um fragmento opt mostra a expiração: 401, refresh, novo par de tokens, nova tentativa.

JSON Web Tokens são populares porque uma API consegue verificar um sem chamar ninguém: confere a assinatura, lê as claims, pronto. Essa mesma propriedade é a origem da maioria dos problemas com JWT. Um token que você não consegue consultar é um token que você não consegue recolher, e os times descobrem isso na primeira vez que um notebook é roubado ou alguém sai da empresa.

Este post percorre um fluxo completo de autenticação JWT com tokens de acesso, refresh tokens e um diagrama de sequência, e depois cobre as verificações de que toda API precisa, onde guardar tokens no navegador, a rotação de refresh tokens, a rotação de chaves e as opções realistas de revogação.

O que é um JWT, e o que ele não é

Um JWT (RFC 7519) é uma string compacta e segura para URL, com três partes em base64url separadas por pontos: um cabeçalho, um payload de claims e uma assinatura. Decodificado, um token de acesso fica assim:

{ "alg": "RS256", "kid": "2026-10", "typ": "at+jwt" }
{
  "iss": "https://auth.example.com",
  "sub": "user_8412",
  "aud": "orders-api",
  "scope": "orders:read orders:write",
  "iat": 1793606400,
  "exp": 1793607300,
  "jti": "a3f1c9e2"
}

Três pontos causam a maior parte dos mal-entendidos:

  • Um JWT assinado não é criptografado. Qualquer pessoa com o token consegue ler o payload. Não coloque nele segredos nem dados pessoais que o portador não deveria ver.
  • JWT é um formato, não um protocolo. Como um cliente obtém um token é definido em outro lugar, normalmente pelo OAuth 2.0 e pelo OpenID Connect. O diagrama de fluxo do OAuth 2.0 cobre essa parte.
  • Nem todo token de um fluxo é um JWT. Tokens de acesso muitas vezes são; refresh tokens muitas vezes são strings aleatórias opacas que só o servidor de autorização consegue consultar.

As claims registradas que você vai encontrar em todo token:

Claim Significado Quem verifica
iss Issuer, o servidor de autorização que assinou o token API
sub Subject, normalmente o ID do usuário API, para a autorização
aud Audience, a API à qual o token se destina API
exp, nbf, iat Expiração, início da validade e horário de emissão, em segundos desde a epoch API
jti ID único do token, útil para listas de bloqueio API ou gateway

O fluxo, passo a passo

  1. Login. O usuário se autentica no servidor de autorização, normalmente pelo fluxo authorization code do OAuth com PKCE.
  2. Resposta com tokens. O servidor de autorização devolve um token de acesso de curta duração (um JWT, digamos de 15 minutos) e um refresh token de longa duração.
  3. Chamada à API. O app envia Authorization: Bearer <access token> em cada requisição.
  4. Validação local. A API verifica a assinatura com a chave pública do servidor de autorização, que ela buscou uma vez no endpoint JWKS e guardou em cache, e depois confere as claims. Nenhuma chamada ao servidor de autorização por requisição.
  5. Expiração. Depois de 15 minutos, a API responde 401 Unauthorized.
  6. Refresh. O app envia o refresh token para o endpoint de tokens do servidor de autorização e recebe um novo token de acesso e, com rotação, um novo refresh token.
  7. Nova tentativa. O app repete a requisição que falhou com o novo token de acesso.

Os passos 3 e 4 são o motivo de os times escolherem JWT: milhares de requisições à API e nenhum repositório de sessões compartilhado. Os passos 5 e 6 são o preço, e é ali que fica a maior parte do trabalho de segurança.

Validar um token: a checklist

Toda API que aceita JWTs deve fazer as mesmas verificações, nesta ordem:

  1. Permita só os algoritmos que você espera. Nunca aceite o cabeçalho alg sem questionar. O RFC 8725 descreve os dois ataques clássicos: alg definido como none, e um token RS256 reescrito como HS256 para que uma biblioteca ingênua o verifique usando a chave pública como segredo HMAC.
  2. Escolha a chave pelo kid no JWKS em cache, e busque o conjunto de novo quando aparecer um kid desconhecido, no máximo uma vez por intervalo curto.
  3. Verifique a assinatura.
  4. Verifique iss e aud. Um token emitido para outra API precisa falhar aqui.
  5. Verifique exp e nbf com uma pequena tolerância de relógio, como 60 segundos.
  6. Verifique o tipo do token. Tokens de acesso do RFC 9068 carregam typ: at+jwt, o que impede que um ID token seja reaproveitado como token de acesso.
  7. Depois autorize: scopes, papéis e propriedade do recurso.

Com a biblioteca jose no Node.js, quase toda a lista é uma única chamada:

import { createRemoteJWKSet, jwtVerify } from 'jose'

const JWKS = createRemoteJWKSet(new URL('https://auth.example.com/.well-known/jwks.json'))

export async function verifyAccessToken(token: string) {
  const { payload } = await jwtVerify(token, JWKS, {
    issuer: 'https://auth.example.com',
    audience: 'orders-api',
    algorithms: ['RS256'],
    typ: 'at+jwt',
    clockTolerance: 60,
  })
  return payload // scopes and sub are checked by the caller
}

Quanto tempo um token de acesso deve durar?

A duração é a janela em que um token roubado funciona e não pode ser recolhido. Mais curta significa mais segura e mais tráfego de refresh. Para um usuário ativo durante uma jornada de oito horas:

Duração do token de acesso Exposição se for roubado Refreshes por usuário por dia
5 minutos 5 minutos 96
15 minutos 15 minutos 32
1 hora 1 hora 8
24 horas 24 horas 1

A maioria dos times fica entre 5 e 15 minutos para tokens de acesso. Um token de acesso que dura um dia é um cookie de sessão que você não consegue revogar.

Rotação de refresh tokens

Um refresh token vive dias ou semanas, então vazar um é pior do que vazar um token de acesso. O RFC 9700, a melhor prática atual de segurança do OAuth, exige uma de duas proteções para refresh tokens mantidos por clientes públicos, como apps de navegador e apps mobile:

  • Refresh tokens vinculados ao remetente, presos a uma chave que o cliente possui, com TLS mútuo ou DPoP.
  • Rotação: cada refresh devolve um novo refresh token e invalida o anterior, enquanto o servidor de autorização guarda a cadeia. Se um atacante e o cliente legítimo usam o mesmo token, um deles apresenta um token invalidado, e o servidor revoga o refresh token ativo, o que encerra a cadeia para os dois.

A rotação transforma um refresh token roubado, que seria um problema de semanas, em um problema que acaba no próximo refresh do cliente legítimo. O custo: o usuário precisa entrar de novo, e o seu endpoint de tokens precisa lidar com duas abas fazendo refresh ao mesmo tempo sem disparar a detecção de reutilização, normalmente com um curto período de tolerância.

Onde guardar tokens no navegador

Armazenamento Legível por JavaScript Risco principal Observações
localStorage Sim Qualquer XSS pode roubar os tokens Sobrevive a recarregamentos; evite para refresh tokens
Só em memória Sim, enquanto a página existir XSS durante a sessão Some ao recarregar; faça refresh na inicialização
Cookie HttpOnly Não CSRF Use Secure, SameSite e tokens CSRF nas requisições que mudam estado
Backend for frontend Não; os tokens ficam no servidor Gestão de sessões no servidor O navegador só guarda um cookie de sessão

O rascunho do IETF sobre OAuth para aplicações baseadas em navegador descreve o padrão backend for frontend como a opção que mantém os tokens totalmente longe do JavaScript. Se você mantiver tokens no navegador, deixe o token de acesso em memória e o refresh token em um cookie HttpOnly restrito ao endpoint de tokens.

Revogação: o que funciona de verdade

Você não consegue “desassinar” um JWT. Só consegue fazer a API parar de aceitá-lo, e cada opção devolve um pouco do estado que você evitava:

Estratégia Como funciona Custo
Expiração curta Os tokens morrem sozinhos em minutos Nenhum; a janela de exposição continua
Revogar o refresh token O próximo refresh falha, então o acesso termina na próxima expiração Uma consulta no endpoint de tokens, que já tem estado
Lista de bloqueio por jti Gateways rejeitam os IDs listados até o exp deles Um cache compartilhado, consultado em toda requisição
Corte por usuário Rejeitar tokens emitidos antes de um timestamp guardado para aquele usuário Uma consulta por usuário, cacheável
Introspecção A API pergunta ao servidor de autorização sobre cada token (RFC 7662) Uma chamada de rede; use só em endpoints de alto risco

Uma combinação prática: tokens de acesso de 15 minutos ou menos, refresh tokens rotativos revogados no logout e na troca de senha, e um corte por usuário para o caso raro de “sair de todos os lugares agora”.

Rotacionar as chaves de assinatura

Chaves vazam e algoritmos envelhecem, então planeje a rotação desde o primeiro dia. Publique a nova chave pública no JWKS mais ou menos um dia antes de assinar com ela, para que todo cache de API já a tenha. Mude a assinatura para o novo kid. Mantenha a chave antiga no JWKS até expirar o último token assinado com ela e depois remova-a. Uma API que busca o conjunto de novo quando vê um kid desconhecido sobrevive a uma rotação de emergência sem reiniciar.

O diagrama do fluxo JWT

Diagrama de sequência com três linhas de vida: app de navegador, servidor de autorização e API de pedidos. O login devolve um token de acesso e um refresh token. O app chama a API com um token bearer. Um fragmento opt mostra a expiração: 401, refresh, novo par de tokens, nova tentativa.

5 componentes · 12 conexões

Abrir no Archboard
Conteúdo do diagrama
  • Browser app
  • Auth server
  • Orders API
  • access token expired
  • 1. Sign in (OAuth code flow + PKCE)
  • 2. Access token (JWT, 15 min) + refresh token
  • 3. GET /orders, Authorization: Bearer JWT
  • GET /.well-known/jwks.json (once, then cached)
  • public keys
  • 4. 200 OK
  • 5. GET /orders (expired JWT)
  • 6. 401 Unauthorized
  • 7. POST /token (refresh token)
  • 8. New token pair, old refresh token invalidated
  • 9. Retry GET /orders with new JWT
  • 10. 200 OK
Um app de navegador faz login, chama uma API com um token de acesso JWT de curta duração e usa um refresh token rotativo quando o token de acesso expira. A API valida os tokens localmente com chaves do endpoint JWKS do servidor de autorização.

Como ler:

  • Três linhas de vida. O app de navegador à esquerda, o servidor de autorização no meio e a API de pedidos à direita. O tempo corre para baixo.
  • O login e a resposta com tokens ficam no topo: o app recebe um token de acesso e um refresh token.
  • O caminho feliz: a requisição bearer para a API e a resposta. A API valida o token com as chaves JWKS em cache e nunca chama o servidor de autorização.
  • O fragmento opt cobre a expiração: 401, refresh, um novo par de tokens com o refresh token antigo invalidado e a requisição repetida.
  • O bloco Markdown mostra o token decodificado e as verificações de validação.

Desenhar fluxos de autenticação que os revisores consigam conferir

  • Nomeie cada token em cada seta, com tipo e duração: “token de acesso (JWT, 15 min)”. A ambiguidade sobre qual token vai para onde esconde bugs reais.
  • Mostre onde a validação acontece. Coloque uma nota na linha de vida que verifica a assinatura e diga de onde vêm as chaves dela.
  • Desenhe os caminhos de falha. Expiração, reutilização de refresh token e logout cabem em fragmentos; a maioria dos incidentes começa ali.
  • Deixe os segredos fora da figura. Use valores fictícios; diagramas são compartilhados mais do que você imagina.

O exemplo de diagrama de sequência cobre linhas de vida e fragmentos em detalhe, e o diagrama de arquitetura zero trust mostra onde as verificações de token ficam em um modelo de acesso mais amplo.

Monte no Archboard

  1. Entre com Google ou GitHub e crie um diagrama.
  2. Adicione três nós Linha de vida do pack Sequência: Browser app, Auth server e Orders API.
  3. Desenhe as mensagens como arestas entre as linhas de vida, de cima para baixo: login, resposta com tokens, a requisição bearer e a resposta dela. Rotule cada uma com o token que ela carrega.
  4. Adicione um Fragmento combinado do pack Sequência com o operador opt em volta do caminho de expiração: 401, pedido de refresh, novo par de tokens, nova tentativa.
  5. Adicione um bloco Markdown do pack Básico com o token decodificado e a checklist de validação.

O exemplo usa 5 nós de diagrama e fica dentro do plano Free.

Perguntas frequentes

JWTs são criptografados? JWTs assinados não são. O payload é codificado em base64url e qualquer pessoa com o token consegue lê-lo. Existe o JSON Web Encryption para tokens criptografados, mas a maioria dos tokens de acesso é apenas assinada.

Devo guardar um JWT no localStorage? Evite para qualquer coisa de longa duração. Qualquer bug de cross-site scripting consegue ler o localStorage. Mantenha tokens de acesso em memória e refresh tokens em um cookie HttpOnly, ou mantenha os tokens em um backend for frontend.

Como faço logout de um usuário se os JWTs não têm estado? Revogue o refresh token para que nenhum token de acesso novo seja emitido, e mantenha os tokens de acesso curtos. Para efeito imediato, adicione um timestamp de corte por usuário ou uma lista de bloqueio por jti que a sua API verifique.

Qual é a diferença entre um ID token e um token de acesso? Um ID token diz ao cliente quem fez login e é destinado ao cliente. Um token de acesso é destinado a uma API. As APIs devem rejeitar ID tokens; as verificações de typ e aud deixam isso explícito.

Devo usar HS256 ou RS256? O HS256 usa um único segredo compartilhado, então todo serviço que verifica tokens também consegue emiti-los. O RS256 ou o ES256 permite que as APIs verifiquem com uma chave pública enquanto só o servidor de autorização guarda a chave privada, que é o padrão mais seguro quando há mais de um serviço.

Comece grátis — um assento, sem cartão de crédito.

Artigos relacionados

← Voltar ao blog

Abra um canvas em um minuto

Entre com Google ou GitHub. Grátis para um assento. Faça upgrade quando a equipe entrar.