Desenvolvimento Web

Segurança em APIs REST: autenticação, autorização e proteção contra os ataques mais comuns

Segurança em APIs REST: autenticação, autorização e proteção contra os ataques mais comuns

APIs são a superfície de ataque mais explorada da web moderna. Cada endpoint exposto é uma porta que precisa estar corretamente trancada: autenticação verificando quem você é, autorização verificando o que você pode fazer, e proteção contra injeção, rate limiting e vazamento de dados. A maioria dos vazamentos de dados não explora vulnerabilidades zero-day — explora APIs mal configuradas e controles de acesso negligenciados.

JWT: boas práticas além do básico

JSON Web Tokens são onipresentes em APIs, mas implementações incorretas são igualmente comuns. Nunca use o algoritmo “none” (permite assinar tokens sem chave), sempre verifique o campo alg no header antes de validar (ataques de confusão de algoritmo), e prefira RS256/ES256 (assimétrico) sobre HS256 (simétrico) em arquiteturas com múltiplos serviços — a chave privada fica em um só lugar, qualquer serviço pode verificar com a chave pública. Expiração curta (15 minutos) com refresh tokens de longa duração é o padrão correto: access tokens comprometidos expiram rapidamente, e refresh tokens podem ser revogados individualmente.

Refresh token rotation é a prática de emitir um novo refresh token a cada renovação de access token, invalidando o anterior. Se um refresh token roubado for usado, o token legítimo do usuário para de funcionar quando ele tentar renovar — detectando o comprometimento. Armazene refresh tokens em banco de dados (com hash, como senhas), não apenas como JWT auto-contidos — isso permite revogação imediata em caso de logout ou detecção de atividade suspeita. Para APIs de serviço-a-serviço, Client Credentials flow do OAuth 2.0 com escopos granulares é mais adequado que tokens mutipropósito.

Autorização: RBAC, ABAC e o princípio do menor privilégio

Autenticação confirma identidade. Autorização define permissões. Role-Based Access Control (RBAC) é o mais comum: cada usuário tem um ou mais roles (admin, editor, viewer), e cada endpoint verifica roles. Simples de implementar, mas rígido para cenários complexos: “usuário pode editar seus próprios posts mas não os de outros” não se encaixa bem em RBAC puro. Attribute-Based Access Control (ABAC) avalia atributos do sujeito, do objeto e do ambiente — mais expressivo, mais complexo.

Na prática, combine: RBAC para controle grosseiro (usuário autenticado vs admin), verificações de propriedade para controle fino (post.user_id === req.user.id). Nunca confie no ID de recurso enviado pelo cliente sem verificar que aquele usuário tem acesso àquele recurso específico — IDOR (Insecure Direct Object Reference) é uma das vulnerabilidades mais comuns e mais fáceis de introduzir inadvertidamente. Toda query ao banco deve incluir o user_id como filtro: SELECT * FROM pedidos WHERE id = $1 AND user_id = $2 — se retornar vazio, 404, não 403 (não revele que o recurso existe).

Rate limiting e proteção contra abuso

Rate limiting protege contra força bruta, scraping e DoS. Implemente em múltiplas dimensões: por IP (100 requests/minuto para todos), por usuário autenticado (1000 requests/hora por conta), e por endpoint específico (5 tentativas de login por minuto por IP+usuário). O algoritmo Token Bucket (permite bursts controlados) ou Sliding Window (mais preciso) são preferíveis ao Fixed Window (facilmente burlado com timing nas bordas da janela). Redis com Lua scripts garante atomicidade nas contagens distribuídas.

Headers Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset informam o cliente sobre os limites e quando pode tentar novamente — reduzindo retries desnecessários e melhorando a experiência de quem usa a API legitimamente. Para login, CAPTCHA após N falhas e bloqueio progressivo (1 minuto, 5 minutos, 30 minutos) frustram ataques de força bruta sem bloquear usuários que simplesmente esqueceram a senha. Notificações de login em dispositivo novo ou localização incomum são camada extra de detecção sem degradar UX.

Input validation e prevenção de injeção

Nunca confie em dados do cliente. Valide estritamente o schema de cada request com bibliotecas como Zod (TypeScript), Joi (Node.js), Pydantic (Python) ou Yup. Tipos, formatos, tamanhos máximos, e conjuntos de valores permitidos devem ser validados antes de qualquer processamento. SQL injection continua sendo o vetor mais comum apesar de décadas de conscientização — use parameterized queries ou ORMs sempre que acessar banco, nunca concatene strings com dados do usuário. Queries como WHERE id = ${req.params.id} são vulneráveis mesmo se o id parece numérico.

Mass assignment é um vetor subestimado: se você passa req.body diretamente para um ORM, um usuário pode enviar campos extras (como is_admin: true) que serão persistidos. Use allowlists explícitas de campos atualizáveis. XSS stored via API ocorre quando a API persiste HTML/JavaScript não sanitizado que depois é renderizado pelo frontend — sanitize outputs com DOMPurify no cliente ou bleach no servidor para qualquer dado que será renderizado como HTML. Logging sensitivo é outro risco: nunca logue passwords, tokens, ou PII em logs de aplicação — um log comprometido é equivalente a um banco de dados comprometido.

Tem um projeto em mente?

Somos especialistas em transformar ideias em produtos digitais. Apps, sites, automações e IA — vamos construir juntos.

Resposta rápida Orçamento sem compromisso +100 projetos entregues
Compartilhar: