Crachá e salas
O crachá na entrada (autenticação) não abre o cofre. Cada porta tem uma lista de quem entra (autorização). Olhar pela janela se a porta “parece” trancada (UI) não tranca a porta.
Quem pode, de verdade
A pergunta certa é por ação e por recurso: este user pode apagar *este* post?
Guards são Chain of Responsibility na borda da rota: cada elo pode barrar.
RBAC escala bem com poucos papéis estáveis. Quando a regra depende de atributo (horário, tenant, valor), ABAC/policies evitam explosão de roles.
JWT com roles no claim acelera a checagem, mas roles revogadas no banco só somem no próximo token — para admin demovido, revalide ou use TTL curto.
Como isso aparece na prática
Painel com admin e suporte
Cenário
Suporte pode ler tickets; só admin apaga usuários.
Como o padrão entra
Roles no user; requireRoles('admin') nas rotas destrutivas; auditoria append-only nas ações admin.
Trade-off: Suporte pressiona por mais poder — resista a virar tudo admin; crie permissões finas.
IDOR na API de pedidos
Cenário
GET /pedidos/123 devolvia qualquer pedido se o user estivesse logado.
Como o padrão entra
Além do guard de autenticação, filtrar where userId = req.user.id (ou admin).
Trade-off: Queries um pouco mais verbosas; testes de autorização passam a ser obrigatórios.
Onde isto dá errado
Guard que só checa `user != null`
Isso é autenticação disfarçada. Qualquer conta válida passa — inclusive a do atacante recém-criada.
Autorização só no frontend
Esconder o botão não esconde o endpoint. O enforcement é no servidor.
403 e 401 trocados
401 = autentique-se; 403 = você não pode. Clientes e caches se comportam diferente — não misture.
Roles + dono do recurso
// Autenticacao coloca req.user. Autorizacao decide a acao.
// Guard/middleware: role ou permissao explicita — nao so "tem user".
type Role = "user" | "editor" | "admin";
function requireRoles(...roles: Role[]) {
return (req: any, res: any, next: any) => {
if (!req.user) return res.status(401).json({ erro: "nao autenticado" });
if (!roles.some((r) => req.user.roles.includes(r))) {
return res.status(403).json({ erro: "proibido" });
}
next();
};
}
// Rota sensivel: precisa ser editor OU admin.
app.delete("/posts/:id", requireRoles("editor", "admin"), apagarPost);
// IDOR: alem do role, o recurso precisa pertencer ao user (ou admin).
async function apagarPost(req: any, res: any) {
const post = await posts.byId(req.params.id);
if (!post) return res.status(404).end();
const dono = post.authorId === req.user.id;
const admin = req.user.roles.includes("admin");
if (!dono && !admin) return res.status(403).end();
await posts.apagar(post.id);
res.status(204).end();
}Quando usar × quando evitar
Use quando
2- Ações e dados que diferem por papel ou dono.
- APIs expostas a mais de um tipo de usuário.
Evite quando
2- Antes de haver autenticação sólida.
- Só no cliente, sem a mesma regra no servidor.
Testar o que ficou
3 armadilhas de Autorização (RBAC e guards) viram perguntas, com o nome do padrão escondido, misturadas com padrões parecidos.
Onde isto aparece de verdade
Você já usa isto, talvez sem saber o nome.
Guards do NestJSCanActivate que roda antes do handler e decide 401/403 por role ou policy.middleware do Express / NextCadeia que inspeciona a sessão e barra a rota antes da lógica de negócio.IAM roles / policiesA mesma ideia na nuvem: identidade autenticada + permissões explícitas por ação.
O padrão em uma linha
Sem nome de domínio, sem cerimônia. Só a ideia.
// Autenticado ≠ autorizado. Role (ou policy) na porta.
if (!req.user.roles.includes("admin")) return res.status(403).end();O que ele cobra
1 salto a mais entre a chamada e o efeito.
- Modelar roles/permissões e mantê-las alinhadas ao produto
- Guards demais espalhados sem política central viram inconsistência
Não vale se: todo usuário autenticado pode tudo da mesma forma — aí autenticação basta e roles são teatro.
Costuma ser confundido com
Onde isto aparece
Continue por aqui
- AutenticaçãoAutenticação responde *quem você é*: prova de identidade antes de qualquer permissão. Na web, o desenho padrão é sessão no servidor com cookie httpOnly, Secure e SameSite — o token opaco mora fora do alcance do JavaScript da página. Confundir autenticação com autorização, ou guardar a prova de identidade no localStorage, é o caminho mais curto para vazamento e abuso.
- JWTJSON Web Token é um formato de credencial assinada: o servidor (ou o IdP) embute claims e uma assinatura, e quem recebe verifica sem necessariamente consultar um store de sessão. Útil para APIs e SSO — perigoso quando vira “auth completo” com token eterno no localStorage, algoritmo `none`, ou sem plano de refresh e revogação.
- Chain of ResponsibilityPassa uma requisição por uma corrente de manipuladores; cada um decide se trata ou repassa adiante, sem que o remetente saiba quem vai atender.
- ProxyColoca um substituto com a mesma interface na frente de um objeto para controlar o acesso a ele — adiando a criação, cacheando resultados, checando permissão ou falando com um objeto remoto.
- API GatewayNum sistema de muitos serviços, um ponto único de entrada por onde tudo passa: o API Gateway roteia cada requisição ao serviço certo e concentra o que é transversal — autenticação, rate limiting, CORS, log — para os serviços não repetirem isso cada um. O cliente conhece só o gateway, e a topologia interna pode mudar por trás. O risco é o gateway virar gargalo, ponto único de falha, ou um monólito de fronteira inchado de regra.