1001Ferramentas
🛡️ Geradores

Gerador OAuth State

Gera tokens state aleatórios seguros (128 bits) para proteção CSRF em fluxos OAuth 2.0. Recomendado pela RFC 6749.

State OAuth assinado: codificando intenção dentro do parâmetro

Existem duas escolas para o parâmetro state do OAuth 2.0. A abordagem aleatória opaca gera uma string de alta entropia, armazena no servidor e compara no callback. A abordagem signed claims embute dados estruturados — nonce anti-CSRF, URL de retorno, intenção do usuário, variante A/B — dentro do próprio state e prova integridade com um HMAC. Ambas previnem CSRF; o state assinado adicionalmente permite que o callback reconstrua contexto sem armazenamento de sessão, o que é decisivo para runtimes serverless e edge (Cloudflare Workers, Vercel Edge, AWS Lambda) onde sessões sticky são caras ou impossíveis.

Um layout típico de state assinado codifica um payload JSON e anexa uma tag HMAC-SHA256, separados por um ponto:

payload = base64url(JSON.stringify({
  csrf: random(16),       // nonce anti-CSRF
  return_url: "/dashboard",
  intent: "signup",       // signup | login | link
  variant: "B",           // braço do A/B test
  iat: 1716902400,        // issued-at (unix)
  ttl: 600                // 10 minutos
}))
tag = base64url(HMAC_SHA256(STATE_SECRET, payload))
state = payload + "." + tag

Fluxo de validação no callback

Faça split pelo ponto, recompute o HMAC sobre o payload e compare em tempo constante (crypto.timingSafeEqual). Só depois da tag bater, faça parse do JSON. Em seguida cheque iat + ttl > agora para impor janela de 5-10 minutos — curta o bastante para derrotar replay, longa o bastante para usuários legítimos em rede instável. Rejeite tudo mais velho. Por fim, valide return_url contra uma allowlist de caminhos do mesmo origin para evitar open redirect.

JWT vs HMAC custom

Você pode usar um JWT (jsonwebtoken, jose) para o mesmo papel — as claims exp/iat e assinatura HS256 mapeiam direto em state assinado. JWT é overkill para um valor que vive 10 minutos: o header adiciona bytes e os footguns de algorithm confusion ("alg":"none") são reais. HMAC custom mantém o state mais curto para o orçamento de URL e evita parsers surpresa. libsodium / tweetnacl oferecem crypto_auth se quiser HMAC fora da stdlib.

Higiene e rotação de segredo

Escolha um segredo de 256 bits (32 bytes aleatórios), guarde na variável de ambiente STATE_SECRET, nunca commit no git. Faça rotação mantendo um pequeno keyring — segredo atual e anterior — verificando contra qualquer chave ativa dentro da janela de TTL. Após rotacionar, a chave antiga pode ser aposentada em 10 minutos já que nenhum state em voo sobrevive ao TTL. OAuth 2.1 ainda recomenda state ao lado do PKCE (agora obrigatório); defendem camadas diferentes.

FAQ

Prefiro state assinado a store no servidor? Sim se você é stateless (serverless, edge). Não se já mantém session store — state aleatório é mais simples e fica opaco.

HMAC-SHA256 é forte o bastante? Sim — com segredo de 256 bits é a mesma primitiva por trás de HS256 JWTs, AWS request signing e TLS PRFs. O elo fraco é a disciplina de rotação, não o algoritmo.

Qual TTL ideal? 5-10 minutos para fluxos interativos. Janelas maiores vazam por redirects e shoulder-surfing; menores derrubam usuários reais em rede ruim.

State assinado dispensa PKCE? Não. PKCE liga o authorization code ao cliente original; state assinado defende a URL de callback contra CSRF. Mitigam ataques diferentes e OAuth 2.1 exige ambos para clientes públicos.

Ferramentas Relacionadas