Pular para o conteúdo
10 min de leitura

Autorização na prática: RBAC, ABAC e ReBAC sem furos

Compartilhar

Por Lucas Andrade ·

RBAC, ABAC e ReBAC explicados na prática: como modelar papéis e permissões, evitar IDOR e decidir autorização no servidor sem furos.

Neste artigo

Autorização é onde muitas aplicações seguras em todo o resto acabam falhando. É comum ver sistemas com autenticação impecável, senhas bem protegidas, transporte cifrado, e ainda assim vulneráveis porque, uma vez que o usuário está logado, a aplicação não controla direito o que cada um pode fazer e ver. Autorização é a disciplina de responder, a cada requisição, à pergunta "esse usuário tem permissão para esta ação sobre este recurso?". Responder isso de forma consistente, no lugar certo e sem furos é mais difícil do que parece, e é o que separa uma aplicação que protege dados dos usuários de uma que os expõe.

Este texto percorre os modelos de autorização mais usados, RBAC, ABAC e ReBAC, mostra quando cada um serve, e aterrissa nas regras práticas que evitam as falhas mais comuns, como o acesso indevido a recursos de outros usuários e o vazamento entre inquilinos em sistemas multi-tenant.

Autenticação não é autorização

Antes de tudo, uma distinção que parece óbvia mas que é fonte de confusão constante. Autenticação responde "quem é você?" e termina quando o sistema confirma a identidade do usuário. Autorização responde "o que você pode fazer?" e acontece depois, a cada operação. São camadas separadas. Estar autenticado não dá direito a nada por si só; é apenas o pré-requisito para que a autorização decida. Muitos bugs graves nascem de sistemas que, uma vez confirmada a identidade, param de perguntar sobre permissão e assumem que "usuário logado pode".

RBAC: papéis e permissões

O modelo mais difundido é o controle de acesso baseado em papéis, o RBAC. A ideia é agrupar permissões em papéis e atribuir papéis aos usuários. Em vez de dizer "este usuário pode criar posts, editar posts, apagar comentários", você define um papel de editor com esse conjunto de permissões e atribui o papel ao usuário. Quando alguém muda de função, você troca o papel; quando uma permissão muda, você a ajusta no papel e todos os que o têm são afetados de uma vez.

RBAC é simples de entender, fácil de auditar e cobre bem a maioria dos casos. Um usuário comum, um editor, um administrador: papéis claros, permissões associadas, decisão direta. Para muitas aplicações, RBAC bem feito já resolve. A recomendação prática é começar sempre negando por padrão e conceder apenas o necessário a cada papel, aplicando o princípio do menor privilégio desde o desenho: um papel deve ter o mínimo de permissões para cumprir sua função, nada além.

Os limites do RBAC

RBAC começa a ranger quando as regras dependem de contexto e não só de papel. Se você precisa dizer "um editor pode editar apenas os posts do próprio departamento" ou "um gerente pode aprovar despesas até certo valor", o papel sozinho não carrega essa informação. A tentação é criar papéis cada vez mais específicos, editor-do-departamento-A, editor-do-departamento-B, e logo você tem uma explosão de papéis impossível de manter. Quando isso começa a acontecer, é sinal de que o problema pede um modelo que leve em conta atributos ou relacionamentos.

ABAC: decisão por atributos

O controle de acesso baseado em atributos, o ABAC, decide a partir de características do usuário, do recurso, da ação e do contexto. Em vez de olhar apenas o papel, a regra avalia atributos: o departamento do usuário, a classificação do documento, o horário, a localização, o valor da transação. Uma política ABAC pode expressar "permitir editar se o departamento do usuário é igual ao departamento do documento e o documento não está bloqueado", algo que o RBAC puro não consegue.

ABAC é poderoso e flexível, capaz de expressar regras finas que mudam com o contexto. O custo é a complexidade: políticas de atributo são mais difíceis de escrever, testar e auditar, e é fácil criar regras que interagem de formas inesperadas. Na prática, muitos sistemas combinam RBAC como base, para o grosso das decisões, com atributos para os casos que exigem nuance. Essa combinação costuma ser mais gerenciável do que ABAC puro.

ReBAC: decisão por relacionamento

Um terceiro modelo ganhou força por resolver bem uma classe de problema muito comum: o controle baseado em relacionamento, o ReBAC. Aqui a pergunta central é sobre a relação entre o usuário e o recurso. Você é dono deste documento? É membro deste projeto? Foi convidado para esta pasta? A permissão emana da relação. É o modelo natural para aplicações onde recursos são compartilhados, onde existe hierarquia de pastas, onde grupos herdam acesso, onde "quem criou é dono".

Motores dedicados de autorização por relacionamento, como OpenFGA e SpiceDB, foram criados justamente para modelar e consultar essas relações em escala, respondendo rapidamente a perguntas do tipo "este usuário tem acesso a este recurso, considerando toda a teia de relacionamentos e heranças?". Para produtos complexos de colaboração e multi-tenant, esse tipo de motor centraliza a decisão de autorização num lugar consistente, em vez de espalhá-la em condicionais soltas pelo código.

As regras práticas que evitam furos

Escolher um modelo é metade do trabalho; a outra metade é aplicá-lo sem deixar brechas. Aqui estão as regras que, na prática, separam a autorização robusta da que vaza.

Negar por padrão

Todo sistema de autorização deve partir do "ninguém pode nada" e abrir explicitamente. Se uma requisição chega a um ponto onde nenhuma regra a permitiu, ela é negada. O oposto, permitir por padrão e tentar bloquear o que é proibido, garante que qualquer rota nova ou esquecida nasça aberta. Deny-default transforma o esquecimento em negação segura em vez de exposição.

A decisão é sempre no servidor

Esconder um botão na interface para quem não é administrador é experiência do usuário, não controle de acesso. O cliente é território do atacante: ele pode chamar a API diretamente, ignorar a interface, forjar requisições. Toda decisão de autorização precisa ser tomada e imposta no servidor, a cada requisição, sobre a identidade verificada no token. A interface pode refletir a permissão para melhorar a experiência, mas a rota tem que reverificar por conta própria, sempre.

Cheque a posse do recurso, não só o login

A falha mais comum e mais explorada é o acesso indevido a objeto de outro usuário, o IDOR, também chamado de BOLA em APIs. Acontece quando a aplicação verifica que o usuário está logado e tem o papel certo, mas não verifica se aquele recurso específico pertence a ele. O usuário pede o pedido de número tal, a aplicação confirma que ele é um cliente válido e devolve o pedido, sem checar se aquele pedido é dele. Trocando o identificador na URL, ele lê os pedidos dos outros. A defesa é checar, em toda operação por identificador, se o recurso pertence ao usuário ou se ele tem uma relação que o autoriza. Esse é um dos furos centrais tratados na segurança de APIs e um dos itens permanentes do OWASP Top 10.

Isole os inquilinos em multi-tenant

Em sistemas que servem várias organizações no mesmo software, o vazamento entre inquilinos é catastrófico: uma empresa vê os dados de outra. A regra inegociável é que o identificador do inquilino vem sempre do token verificado, nunca de um campo do corpo, da query ou de um cabeçalho que o cliente controla. Se você confia no inquilino informado pelo cliente, um atacante simplesmente informa o inquilino da vítima e acessa os dados dela. Toda consulta ao banco precisa ser recortada pelo inquilino da identidade autenticada, e essa amarração tem que ser estrutural, não opcional.

Separe quem decide de quem impõe

Uma arquitetura limpa separa o ponto que decide a autorização, o PDP, do ponto que a impõe, o PEP. O código que atende a requisição pergunta ao motor de decisão "esta ação é permitida?" e obedece à resposta, em vez de espalhar a lógica de permissão por toda parte. Centralizar a decisão facilita mudar regras, testar e auditar, e reduz a chance de duas partes do sistema decidirem de formas diferentes sobre a mesma coisa.

Audite as decisões

Registre as decisões de autorização, especialmente as negações e as ações sensíveis. Uma trilha de auditoria permite investigar incidentes, detectar tentativas de abuso e provar conformidade. Autorização sem registro é uma caixa-preta; quando algo dá errado, você quer poder reconstruir quem tentou o quê e o que foi permitido.

Como escolher entre os modelos na prática

Diante de RBAC, ABAC e ReBAC, a pergunta que todo time faz é qual escolher, e a resposta honesta é que a escolha segue a forma do seu domínio, não a moda. Comece pelo mais simples que resolve. Se as permissões da sua aplicação se organizam bem em poucos perfis de usuário, com regras que não dependem de contexto nem de posse compartilhada, o RBAC puro é suficiente e você não deve complicar. Adicionar atributos ou relacionamentos onde o papel já bastava só cria complexidade sem ganho, e complexidade em autorização é onde os furos se escondem.

Você sabe que precisa de mais quando começa a criar papéis cada vez mais específicos para expressar exceções. Quando surge o "editor, mas só do próprio departamento", ou "gerente, mas só até certo valor", o papel deixou de carregar a informação necessária, e forçar isso em papéis leva à explosão que torna o sistema impossível de manter. É o sinal de migrar para uma decisão que considere atributos. E quando o cerne do produto é compartilhamento de recursos, com donos, convidados, pastas que herdam acesso e grupos, a pergunta de autorização é sempre sobre a relação entre o usuário e o recurso, e aí o modelo por relacionamento é o que expressa isso com naturalidade, em vez de contorções.

Na prática, muitos sistemas maduros combinam camadas: um RBAC de base para as decisões grosseiras de papel, atributos para as regras contextuais, e verificação de posse ou relacionamento para o acesso a recursos específicos. O importante não é a pureza do modelo, mas que a decisão seja consistente, centralizada e imposta no servidor. Um sistema com RBAC simples e uma checagem de posse rigorosa em cada recurso é muito mais seguro do que um ABAC sofisticado cheio de exceções mal testadas. A sofisticação do modelo nunca compensa a falta das regras práticas de negar por padrão, decidir no servidor e checar a posse; ela apenas dá mais ferramentas para expressar o que o domínio exige, quando o domínio de fato exige.

Conclusão

Autorização robusta começa pela escolha certa de modelo: RBAC para o grosso das decisões por papel, atributos quando o contexto importa, relacionamento quando recursos são compartilhados e a posse manda. Mas o modelo só protege se as regras práticas forem seguidas com rigor: negar por padrão, decidir sempre no servidor sobre a identidade verificada, checar a posse do recurso a cada operação por identificador, isolar inquilinos pelo token e nunca pelo cliente, centralizar a decisão e auditá-la. A maioria dos vazamentos de dados por autorização não vem de um modelo errado, mas do esquecimento de uma dessas regras num canto do código. Autorização é uma disciplina de consistência: um único ponto que confia no cliente ou pula a checagem de posse abre a porta que todo o resto tentava fechar.

Compartilhar

Compartilhar

Leituras relacionadas

Nenhum comentário ainda

Seja o primeiro a comentar.

Deixe seu comentário

Entre com sua conta Canverly para comentar. Você pode usar a mesma conta em qualquer site da rede.

Entrar com Canverly