O login funciona. O usuário coloca e-mail, senha, passa pelo magic link, entra no painel e vê a tela certa.
Para muita gente, isso vira sinônimo de segurança.
Não é.
Login responde uma pergunta importante: quem é você?
Mas um SaaS seguro precisa responder outra pergunta em toda ação sensível: você pode acessar este dado específico?
É aí que muitos sistemas construídos rápido com Cursor, Bolt, Lovable ou qualquer fluxo de IA começam a falhar em silêncio.
O erro não aparece na tela
Quando uma feature quebra, todo mundo percebe. O botão não funciona. A tela fica branca. O deploy falha.
Quando uma regra de autorização está errada, a tela pode continuar linda.
O usuário certo entra. O menu aparece. A tabela carrega. A API responde com 200 OK.
O problema é que o dado carregado talvez não pertença àquele usuário.
Esse é o tipo de falha que mais assusta em SaaS: ela não parece um bug. Parece uma feature funcionando.
Autenticação não é autorização
Autenticação é provar identidade.
Autorização é decidir o que aquela identidade pode fazer.
Um exemplo simples:
/dashboard/clientes/42/faturas
Se o usuário autenticado pode trocar 42 por 43 e ver faturas de outro cliente, o login não protegeu o que precisava proteger.
O sistema soube quem era o usuário.
Mas não verificou se aquele usuário tinha permissão para acessar aquele cliente.
O nome técnico disso costuma aparecer como IDOR ou BOLA. Na prática, significa uma coisa simples: o cliente influenciou qual dado seria buscado, e o servidor acreditou.
O frontend não é fronteira de segurança
Um erro comum é achar que esconder o botão resolve.
“Mas essa rota nem aparece para esse usuário.”
Isso só protege contra quem usa a interface do jeito esperado.
Um atacante não precisa clicar no seu botão. Ele pode abrir o DevTools, observar a requisição, trocar um identificador e chamar a API diretamente.
Se a proteção existe apenas no React, no menu, no botão, no redirect ou no estado do frontend, ela não é proteção de verdade.
Segurança de acesso precisa estar no servidor.
É o backend que deve decidir qual user_id, organization_id, tenant_id ou workspace_id vale para aquela sessão. Não o navegador.
O padrão que aparece em código gerado por IA
Ferramentas de IA são muito boas em fazer o caminho feliz funcionar.
Você pede:
Crie uma página para listar as faturas do cliente.
A IA gera rota, componente, chamada de API, query no banco e uma tela bonita.
Mas, se você não pediu explicitamente, ela pode não validar a propriedade do dado em todos os pontos.
Ela entrega algo que funciona.
Só que “funciona” não significa “isola corretamente os dados de cada cliente”.
Esse é o ponto perigoso: o sistema pode parecer pronto justamente porque ninguém tentou usar a feature contra ela mesma.
Três perguntas antes do próximo commit
Não dá para reduzir segurança de SaaS a três perguntas. Mas estas três já revelam muito:
- O servidor decide o
tenant_ida partir da sessão, ou aceita esse valor vindo do navegador? - Toda busca por dados sensíveis filtra pelo usuário, organização ou tenant autenticado?
- Se eu trocar um ID na URL, no body ou no query param, o backend barra a tentativa?
Se alguma resposta for “não sei”, existe uma zona cega.
E zona cega em SaaS não é detalhe técnico. É risco de negócio.
O que este post não vai te entregar
Eu poderia transformar isso em uma checklist longa aqui.
Mas seria uma falsa sensação de segurança.
IDOR é só uma das falhas que aparecem quando um produto cresce rápido e a camada de segurança fica implícita. Sessão, cookies, secrets, headers, uploads, logs e isolamento entre clientes entram na mesma conversa.
O objetivo deste artigo é te dar um alerta: login funcionando não prova que os dados estão protegidos.
A pergunta real é outra:
O que o seu sistema permite depois que o usuário já está logado?
É aí que mora o risco.
