Autenticação com tokens no back-end: conceitos e fluxo com JWT

Capítulo 5

Tempo estimado de leitura: 8 minutos

+ Exercício

O que é autenticação stateless com tokens

Em autenticação baseada em tokens, o back-end não precisa manter estado de sessão por usuário (stateless). Em vez disso, após o login, o servidor emite um token assinado que o cliente passa a enviar em cada requisição. O servidor valida o token a cada chamada e decide se a requisição pode prosseguir.

Na prática, isso reduz dependência de armazenamento de sessão no servidor e facilita cenários com múltiplas instâncias (horizontal scaling). Em contrapartida, exige cuidado com expiração, escopo de dados dentro do token e estratégias de revogação/rotação (tratadas em capítulos específicos).

Fluxo prático com JWT: emissão, envio e validação

1) Emissão do token no login

No login, o cliente envia credenciais (ex.: usuário/senha). Se estiverem corretas, o back-end emite um JWT com claims que identifiquem o usuário e o contexto do token, e devolve ao cliente.

  • Entrada: credenciais
  • Processamento: autenticar usuário + montar claims + assinar token
  • Saída: token (e, opcionalmente, metadados como tempo de expiração)
// Exemplo conceitual de resposta do login (JSON) {  "access_token": "<jwt>",  "token_type": "Bearer",  "expires_in": 900 }

2) Envio do token em cada requisição

O cliente deve enviar o token no header HTTP Authorization usando o esquema Bearer:

GET /api/orders HTTP/1.1 Host: api.exemplo.com Authorization: Bearer <jwt>

Boas práticas de transporte:

Continue em nosso aplicativo e ...
  • Ouça o áudio com a tela desligada
  • Ganhe Certificado após a conclusão
  • + de 5000 cursos para você explorar!
ou continue lendo abaixo...
Download App

Baixar o aplicativo

  • Usar sempre HTTPS (TLS) para evitar interceptação.
  • Não enviar o token em query string (evita vazamento em logs, histórico, referer).
  • Evitar armazenar tokens em locais facilmente acessíveis por scripts em páginas (risco de XSS); a estratégia de armazenamento depende do tipo de cliente (SPA, mobile, server-side), mas o princípio é minimizar exposição.

3) Validação do token em cada requisição

Em cada chamada protegida, o back-end executa um pipeline típico:

  • Extrair o token do header Authorization.
  • Verificar formato (Bearer + três partes separadas por ponto).
  • Validar assinatura (integridade e autenticidade).
  • Validar claims (expiração, emissor, audiência etc.).
  • Construir o contexto de segurança (ex.: req.user com sub e permissões) e seguir para a rota.
// Pseudocódigo de middleware de autenticação function authMiddleware(req, res, next) {   const auth = req.headers["authorization"];   if (!auth || !auth.startsWith("Bearer ")) return res.status(401).end();   const token = auth.slice("Bearer ".length);   const decoded = verifyJwtSignature(token); // valida assinatura e decodifica   validateRegisteredClaims(decoded);         // exp, nbf, iss, aud etc.   req.user = { id: decoded.sub, roles: decoded.roles };   next(); }

Erros comuns na validação:

  • Aceitar tokens com algoritmo none ou não restringir algoritmos aceitos.
  • Não validar aud e iss (token emitido para outro serviço pode ser aceito indevidamente).
  • Ignorar exp ou nbf (aceitar token expirado ou ainda não válido).
  • Confiar em claims sem validar assinatura (decodificar Base64 não é verificar).

Estrutura do JWT: header, payload e signature

Um JWT é composto por três partes separadas por ponto:

base64url(header).base64url(payload).base64url(signature)

Header

Metadados sobre como o token foi assinado (ou criptografado, no caso de JWE). Em JWS (o mais comum), inclui:

  • alg: algoritmo de assinatura (ex.: HS256, RS256, ES256).
  • typ: geralmente JWT (opcional).
  • kid: identificador da chave (útil para rotação de chaves).
{ "alg": "RS256", "typ": "JWT", "kid": "key-2026-01" }

Payload

Contém as claims (declarações) sobre o sujeito e o contexto do token. Importante: em JWS, o payload é apenas codificado em Base64URL, não é secreto. Qualquer pessoa com o token consegue ler o payload.

{ "sub": "user_123", "iss": "https://auth.exemplo.com", "aud": "api.exemplo.com", "exp": 1760000000, "iat": 1759996400 }

Signature

É o resultado da assinatura do header+payload com uma chave. A assinatura garante:

  • Integridade: o conteúdo não foi alterado.
  • Autenticidade: foi emitido por quem possui a chave de assinatura.

Ela não garante confidencialidade do payload.

Claims padrão (registered claims) e como validar

Claims padrão ajudam interoperabilidade e validações consistentes. As mais usadas em APIs:

ClaimSignificadoComo usar/validar
subSubject (identificador do usuário/entidade)Usar como ID principal do usuário; não colocar PII desnecessária.
audAudience (para quem o token foi emitido)Validar se corresponde à API/serviço atual.
issIssuer (quem emitiu)Validar contra a URL/identificador do seu provedor de autenticação.
expExpiration timeRejeitar se now >= exp (considerar clock skew pequeno).
iatIssued atÚtil para auditoria e algumas políticas (ex.: invalidar tokens antes de uma data).
nbfNot beforeRejeitar se now < nbf.

Recomendação prática: defina um conjunto mínimo de validações obrigatórias para qualquer endpoint protegido: assinatura, exp, iss e aud. Use nbf quando fizer sentido (ex.: tokens emitidos para uso futuro).

Claims customizadas: o que colocar (e o que evitar)

Claims customizadas são úteis para reduzir consultas ao banco em cada requisição, mas devem ser usadas com cuidado porque aumentam o tamanho do token e podem ficar desatualizadas até expirar.

Boas opções de claims customizadas

  • roles ou scope: lista de papéis/escopos para autorização.
  • tenant_id: em sistemas multi-tenant, para reforçar isolamento.
  • amr (método de autenticação) ou mfa: sinalizar se houve MFA, quando aplicável.

Evite colocar no token

  • Dados sensíveis: senha (óbvio), hashes, tokens de terceiros, segredos, chaves de API.
  • PII desnecessária: CPF, endereço, telefone, data de nascimento, e-mail (a menos que seja estritamente necessário e avaliado).
  • Dados que mudam com frequência: plano atual, status de assinatura, permissões muito dinâmicas (podem ficar inconsistentes).

Regra prática: coloque no token apenas o necessário para identificar o sujeito e tomar decisões rápidas de autorização; todo o resto deve ser buscado sob demanda ou representado por um identificador.

Assinatura (JWS) vs criptografia (JWE)

JWS: JWT assinado (o mais comum em APIs)

JWS (JSON Web Signature) é quando o token é assinado. Ele protege contra adulteração, mas não esconde o conteúdo. Use JWS quando:

  • Você precisa que a API confie que o token foi emitido por um emissor legítimo.
  • O payload não contém informações que precisem ser secretas.
  • Você quer simplicidade e compatibilidade ampla.

Exemplos de algoritmos:

  • HS256: HMAC com segredo compartilhado (mesma chave assina e valida). Exige cuidado com distribuição do segredo entre serviços.
  • RS256/ES256: assimétricos (chave privada assina, pública valida). Bom para múltiplos serviços validadores sem compartilhar segredo de assinatura.

JWE: JWT criptografado

JWE (JSON Web Encryption) criptografa o conteúdo do token, fornecendo confidencialidade. Use JWE quando:

  • Você precisa transportar dados que não podem ser expostos ao cliente ou a intermediários (mesmo com TLS).
  • Há exigências regulatórias/arquiteturais para minimizar exposição de dados no cliente.

Observações importantes:

  • JWE aumenta complexidade e custo de processamento.
  • Mesmo com JWE, ainda é recomendável minimizar dados sensíveis no token; criptografar não elimina riscos como vazamento do próprio token.
  • Em muitos casos, a alternativa mais simples é manter o JWT assinado (JWS) com payload mínimo e buscar dados sensíveis no back-end.

Passo a passo: desenhando um JWT para uma API

Passo 1: Defina o objetivo do token

  • Identificar o usuário? (sub)
  • Restringir a qual API ele serve? (aud)
  • Garantir que veio do emissor correto? (iss)
  • Carregar escopos/papéis para autorização? (scope/roles)

Passo 2: Escolha o tipo de assinatura

  • Monólito ou poucos serviços com segredo bem protegido: HS256 pode ser suficiente.
  • Múltiplos serviços validando tokens: prefira RS256/ES256 para não distribuir a chave privada.

Passo 3: Monte claims mínimas e consistentes

Exemplo de payload enxuto para API:

{ "iss": "https://auth.exemplo.com", "aud": "api.exemplo.com", "sub": "user_123", "iat": 1760000000, "exp": 1760000900, "nbf": 1760000000, "scope": "orders:read orders:write", "tenant_id": "t_9f3a" }

Passo 4: Valide no servidor em todas as rotas protegidas

  • Rejeite tokens sem assinatura válida.
  • Rejeite tokens com iss/aud inesperados.
  • Rejeite tokens expirados ou ainda não válidos.
  • Normalize o contexto do usuário (ex.: converter scope em permissões internas).

Exercícios

Exercício 1: montar um payload adequado

Cenário: uma API api.loja.com recebe tokens emitidos por https://auth.loja.com. O usuário autenticado tem ID u_784, pertence ao tenant tenant_22 e precisa apenas ler pedidos. O token deve durar 15 minutos.

Tarefa: escreva um payload JWT (JSON) contendo claims padrão e customizadas mínimas para esse cenário. Inclua iss, aud, sub, iat, exp e uma claim de escopo/permissão. Use timestamps Unix (segundos) fictícios coerentes (ex.: iat e exp com 900s de diferença).

Exercício 2: identificar riscos de dados sensíveis no token

A seguir, uma lista de claims que alguém propôs colocar no JWT. Para cada item, marque: (A) aceitável, (B) aceitável com ressalvas, (C) não recomendado. Em seguida, justifique em uma frase.

  • email
  • cpf
  • password_hash
  • roles
  • credit_card_last4
  • address
  • tenant_id
  • is_admin
  • refresh_token (incluir o refresh token dentro do access token)

Dica: lembre que em JWS o payload é legível por quem possui o token, e que tokens podem vazar via logs, extensões, XSS, backups e capturas de tráfego em ambientes não protegidos.

Agora responda o exercício sobre o conteúdo:

Em um endpoint protegido por JWT, qual conjunto de validações é recomendado como mínimo antes de aceitar a requisição?

Você acertou! Parabéns, agora siga para a próxima página

Você errou! Tente novamente.

O mínimo recomendado inclui validar a assinatura (integridade/autenticidade) e verificar claims essenciais como exp, iss e aud. Apenas decodificar ou checar formato não impede aceitar tokens adulterados, expirados ou emitidos para outro serviço.

Próximo capitúlo

Assinatura, chaves e validação de JWT no back-end

Arrow Right Icon
Capa do Ebook gratuito Autenticação e Autorização no Back-end: Sessões, JWT e Boas Práticas
28%

Autenticação e Autorização no Back-end: Sessões, JWT e Boas Práticas

Novo curso

18 páginas

Baixe o app para ganhar Certificação grátis e ouvir os cursos em background, mesmo com a tela desligada.