Se você está construindo uma API para um produto digital, especialmente em uma startup, um dos pontos mais críticos é garantir a segurança desde o primeiro deploy. A pressa por entregar MVPs muitas vezes leva a soluções improvisadas de autenticação e autorização, que futuramente viram dívidas técnicas caras.
Com base nas soluções que implementei ao longo dos anos em ambientes Java e cloud (especialmente com Quarkus e AWS), compartilho aqui um guia direto com boas práticas para proteger APIs REST utilizando OAuth2, OpenID Connect e AWS Cognito.
1. Conceitos que você precisa entender primeiro
- Autenticação (Authentication): verificar se o usuário é quem diz ser (ex: login).
- Autorização (Authorization): verificar se esse usuário tem permissão para acessar certo recurso.
- OAuth2: protocolo para autorização segura, usado por APIs modernas.
- OpenID Connect: camada de identidade em cima do OAuth2 (inclui login e perfis).
- JWT: token compactado com as informações do usuário (e do sistema) usado para validar requisições.
2. Por que usar Cognito em Startups?
AWS Cognito é um serviço gerenciado de identidade da AWS. Ele resolve autenticação de forma escalável e segura, com:
- Cadastro/login de usuários
- Recuperação de senha
- Validação por e-mail/SMS
- Suporte a login com Google, Facebook, Apple
- Integração nativa com API Gateway, Lambda e IAM
Ideal para startups que não querem reimplementar do zero.
3. Estrutura de segurança recomendada
- Criar um User Pool no Cognito (base de usuários)
- Criar um App Client com o fluxo de autenticação que deseja (ex: Authorization Code ou Password)
- Configurar o backend (Quarkus, Spring etc.) para validar os tokens JWT emitidos
- Definir roles (admin, user, viewer) e usar nos tokens
- Proteger os endpoints por escopo ou grupo
4. Configurando a API Java com JWT do Cognito
Exemplo com Quarkus:
mp.jwt.verify.publickey.location=https://cognito-idp.sa-east-1.amazonaws.com/<pool-id>/.well-known/jwks.json mp.jwt.verify.issuer=https://cognito-idp.sa-east-1.amazonaws.com/<pool-id> quarkus.oidc.tenant-enabled=true
No código, você pode extrair as informações do token:
@Inject SecurityIdentity identity; String email = identity.getPrincipal().getName(); String companyId = identity.getAttribute("custom:company_id");
5. Protegendo endpoints por Role e Escopo
Com base nas claims do JWT, é possível proteger endpoints de forma simples.
Exemplo:
@RolesAllowed("admin") @GET @Path("/usuarios") public List<Usuario> listarUsuarios() { // apenas admins acessam }
Ou, usando escopos OAuth:
@Authenticated @GET @Path("/dados") @AccessToken( requiredScopes = {"dados:leitura"} )
6. Lidando com tenants (multiempresa)
Se seu sistema é multiempresa (multitenant), inclua o company_id
no JWT.
- Configure uma Lambda de Pre Token Generation no Cognito para enriquecer o token com atributos do banco
- Valide esse
company_id
no backend e associe o acesso aos dados corretos
Exemplo:
String tenantId = identity.getAttribute("custom:company_id"); repository.findByTenantId(tenantId);
7. Cuidados e boas práticas
- Nunca confie em tokens sem validação (sempre use assinatura + expiração)
- Use HTTPS sempre
- Mantenha o tempo de expiração dos tokens curto (ex: 15min)
- Atualize o
JWK
periodicamente se fizer cache - Use refresh tokens com controle de revogação
- Sempre audite acessos sensíveis com
user_id
,ip
,timestamp
Conclusão
Implementar segurança em APIs não precisa ser um monstro. Com OAuth2, OpenID e Cognito você cobre as principais frentes: login, escopo, roles, expiração, auditabilidade e escalabilidade.
Se você está construindo uma API em Java para um produto digital, comece com essas boas práticas e evite dores no futuro. Se quiser conversar mais sobre arquitetura segura para startups, me chama!