Estratégias de autenticação em APIs públicas: API keys vs OAuth vs JWT
1. Introdução aos desafios de autenticação em APIs públicas
APIs públicas expostas à internet enfrentam um dilema fundamental: como permitir acesso controlado a recursos sem comprometer a segurança? Diferentemente de APIs internas, que operam em redes confiáveis, as APIs públicas precisam lidar com requisições de origens desconhecidas, ataques de força bruta, vazamento de credenciais e abuso de limites de taxa.
A primeira distinção crucial é entre autenticação (verificar quem é o cliente) e autorização (determinar o que esse cliente pode fazer). Enquanto a autenticação responde "quem está fazendo a requisição?", a autorização responde "essa requisição é permitida?".
As três estratégias mais adotadas — API Keys, OAuth 2.0 e JWT — atendem a diferentes cenários. API Keys são ideais para integrações simples servidor-a-servidor. OAuth 2.0 brilha quando há delegação de acesso entre aplicações de terceiros. JWT oferece uma abordagem stateless e portátil, frequentemente combinada com OAuth 2.0.
2. API Keys: simplicidade e casos de uso
API Keys são strings únicas geradas pelo provedor da API e enviadas pelo cliente em cada requisição, geralmente no header Authorization, na query string ou no corpo da requisição.
Exemplo de requisição com API Key:
GET /api/v1/dados HTTP/1.1
Host: api.exemplo.com
Authorization: Bearer sk_live_4f6g7h8j9k0l1m2n3o4p5q6r
Prós:
- Implementação trivial: geração, armazenamento e validação são diretos
- Baixa latência: sem necessidade de handshakes complexos
- Ideal para comunicação máquina-a-máquina (M2M)
Contras:
- Falta de granularidade: uma chave dá acesso a tudo que o plano permite
- Dificuldade de revogação: se exposta, é necessário invalidar e redistribuir
- Exposição em client-side: chaves em aplicações frontend podem ser extraídas
Melhores práticas:
- Implementar rotação automática de chaves a cada 90 dias
- Aplicar rate limiting por chave individual
- Armazenar chaves em cofres de segredos (HashiCorp Vault, AWS Secrets Manager)
- Nunca incluir chaves em repositórios Git ou logs
3. OAuth 2.0: delegação de acesso e fluxos complexos
OAuth 2.0 é um framework de autorização que permite que aplicações terceiras acessem recursos em nome de um usuário sem compartilhar sua senha. Os fluxos principais são:
- Authorization Code com PKCE: padrão para aplicações web e mobile
- Client Credentials: para comunicação servidor-a-servidor sem usuário
- Implicit Grant: obsoleto, não recomendado para novos projetos
Fluxo Authorization Code (simplificado):
1. Usuário clica "Login com Google" no app
2. App redireciona para: https://auth.exemplo.com/authorize?response_type=code&client_id=123&redirect_uri=https://app.com/callback
3. Usuário autentica e autoriza
4. Servidor de autorização redireciona para redirect_uri com código: https://app.com/callback?code=abc123
5. App troca código por tokens: POST /token com grant_type=authorization_code
6. Resposta: { "access_token": "eyJhbGci...", "refresh_token": "def456", "expires_in": 3600 }
Trade-offs:
- Complexidade de implementação: múltiplos endpoints, redirects e validações
- Necessidade de servidor de autorização dedicado (Keycloak, Auth0, AWS Cognito)
- Overhead de rede: múltiplas requisições até obter o token final
- Benefícios: escopos granulares, revogação por token, suporte a refresh tokens
4. JWT (JSON Web Tokens): autenticação stateless e portabilidade
JWT é um formato compacto e autossuficiente para transmitir informações entre partes como um objeto JSON. O token é composto por três partes codificadas em Base64URL separadas por pontos: header, payload e signature.
Estrutura de um JWT:
Header: {"alg":"RS256","typ":"JWT"}
Payload: {"sub":"user123","name":"Maria","iat":1719000000,"exp":1719003600}
Signature: RSA-SHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), privateKey)
Token completo:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIiwibmFtZSI6Ik1hcmlhIiwiaWF0IjoxNzE5MDAwMDAwLCJleHAiOjE3MTkwMDM2MDB9.assinatura
Vantagens:
- Stateless: servidor não precisa armazenar sessão, apenas verificar a assinatura
- Autocontido: contém todas as informações do usuário e claims
- Portátil: funciona entre microsserviços sem consulta centralizada
- Eficiente: validação por criptografia assimétrica (RS256) ou simétrica (HS256)
Desafios:
- Revogação complexa: tokens válidos até expirarem — requer blacklists ou tokens de curta duração
- Tamanho do payload: quanto mais claims, maior o token (impacto em headers HTTP)
- Riscos de signature bypass: algoritmos "none" ou chaves fracas em implementações incorretas
Uso combinado: JWT é frequentemente usado como access token em fluxos OAuth 2.0, unindo a delegação do OAuth com a portabilidade do JWT.
5. Comparação prática: segurança, performance e escalabilidade
| Critério | API Keys | OAuth 2.0 | JWT |
|---|---|---|---|
| Facilidade de implementação | Alta | Baixa | Média |
| Segurança | Média | Alta | Alta |
| Granularidade de permissões | Baixa | Alta | Média |
| Performance (validação) | Alta (consulta DB simples) | Média (chamada ao IdP) | Alta (verificação local) |
| Revogação | Difícil | Fácil (revogação centralizada) | Difícil (blacklists ou curta duração) |
| Escalabilidade | Alta | Média | Alta |
| Ataques comuns | Vazamento de chave | CSRF, replay | Signature bypass, replay |
Performance: API Keys exigem consulta a banco ou cache a cada requisição. JWT permite validação local sem I/O. OAuth 2.0 com JWT como access token combina o melhor dos dois mundos: delegação via OAuth + validação stateless via JWT.
6. Implementando uma estratégia híbrida em APIs públicas
Uma abordagem robusta combina API Keys para automação (M2M) com OAuth 2.0 + JWT para usuários finais.
Middleware de autenticação (pseudocódigo):
function authenticate(request):
auth_header = request.headers.get("Authorization")
if auth_header starts with "Bearer ":
token = extract_token(auth_header)
if token contains "sk_" prefix: # API Key
return validate_api_key(token)
else: # JWT (OAuth access token)
return validate_jwt(token)
return 401 Unauthorized
Gerenciamento de tokens:
- API Keys: rotação a cada 90 dias, revogação imediata via admin
- JWT: access tokens com expiração de 15 minutos, refresh tokens com 7 dias
- Revogação centralizada: manter lista negra em Redis para JWT inválidos antes da expiração
Healthcheck e monitoramento:
GET /health/auth
Resposta: {
"api_keys_active": 1250,
"jwt_validations_last_minute": 3400,
"revoked_tokens": 23,
"expiration_policy": "access=15min, refresh=7d"
}
7. Conclusão e recomendações finais
A escolha da estratégia depende do perfil da API:
- API pública para integrações M2M: API Keys com rotação e rate limiting
- API pública com usuários finais e terceiros: OAuth 2.0 + JWT (Authorization Code com PKCE)
- API híbrida: API Keys para automação + OAuth/JWT para usuários
Checklist para decisão:
1. Qual o nível de segurança necessário? (dados sensíveis → OAuth 2.0)
2. Quem são os consumidores? (máquinas → API Keys; humanos → OAuth)
3. Qual a infraestrutura disponível? (sem IdP → JWT puro ou API Keys)
4. Necessita de delegação de acesso? (sim → OAuth 2.0)
Tendências futuras: Passkeys (WebAuthn/FIDO2) para autenticação sem senha e Identidades Descentralizadas (DID/VC) para controle soberano de identidade prometem evoluir ainda mais o cenário de autenticação em APIs públicas.
Referências
- OAuth 2.0 Authorization Framework (RFC 6749) — Documentação oficial do protocolo OAuth 2.0, com especificação completa dos fluxos de autorização
- JSON Web Token (JWT) RFC 7519 — Especificação oficial do formato JWT, incluindo estrutura, claims registradas e algoritmos de assinatura
- API Key Best Practices - Google Cloud — Guia oficial da Google sobre boas práticas para uso de API Keys em APIs públicas
- OAuth 2.0 for Browser-Based Applications (PKCE) - Auth0 — Tutorial prático sobre implementação do fluxo Authorization Code com PKCE para aplicações web
- JWT Handbook - Auth0 — Guia completo sobre JWT, incluindo vulnerabilidades comuns, algoritmos e melhores práticas de implementação