Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

RBAC no Node.js: Guia Prático

Atualizado em: 27 de agosto de 2026

Estação de trabalho usada no desenvolvimento de aplicações Node.js

O RBAC no Node.js organiza autorização por funções, como administrador, gerente, editor e leitor. Cada função recebe permissões, e usuários recebem uma ou mais funções dentro de um contexto, como uma organização ou projeto.

Esse modelo é fácil de explicar e auditar, mas pode crescer de forma descontrolada quando cada exceção vira uma nova função. A implementação correta separa autenticação de autorização, verifica permissões no backend, considera o tenant e registra mudanças de acesso.

Neste guia, você aprenderá a modelar roles e permissions, implementar middleware, trabalhar com multi-tenancy, cachear decisões, revogar acesso, testar rotas e evitar escalada de privilégios.

O que é RBAC?

RBAC significa Role-Based Access Control. A referência RBAC do NIST apresenta o modelo. A OWASP Authorization Cheat Sheet reúne recomendações práticas para autorização.

Para autenticação de tokens, consulte JWT Seguro no Node.js. Para isolamento por organização, veja Multi-Tenancy no Node.js.

Autenticação versus autorização

  • Autenticação: confirma quem é o usuário.
  • Autorização: decide o que ele pode fazer.

Um token válido não significa que o usuário pode acessar qualquer recurso.

Role

Uma role representa um conjunto de responsabilidades:

admin
manager
editor
viewer

Evite nomes vagos como special ou power_user_2.

Permission

Permissões devem representar ações específicas:

project.read
project.create
project.update
project.delete
member.invite
billing.manage

Modelo relacional

CREATE TABLE roles (
  id UUID PRIMARY KEY,
  tenant_id UUID NOT NULL,
  name TEXT NOT NULL,
  UNIQUE (tenant_id, name)
);

CREATE TABLE permissions (
  id UUID PRIMARY KEY,
  code TEXT NOT NULL UNIQUE
);

CREATE TABLE role_permissions (
  role_id UUID NOT NULL REFERENCES roles(id),
  permission_id UUID NOT NULL REFERENCES permissions(id),
  PRIMARY KEY (role_id, permission_id)
);

CREATE TABLE user_roles (
  tenant_id UUID NOT NULL,
  user_id UUID NOT NULL,
  role_id UUID NOT NULL REFERENCES roles(id),
  PRIMARY KEY (tenant_id, user_id, role_id)
);

Roles globais ou por tenant?

Roles de sistema podem ser globais, enquanto roles customizadas pertencem ao tenant. Mantenha a distinção explícita.

Permission check

async function hasPermission({
  tenantId,
  userId,
  permission
}) {
  const result = await pool.query(`
    SELECT 1
    FROM user_roles ur
    JOIN role_permissions rp
      ON rp.role_id = ur.role_id
    JOIN permissions p
      ON p.id = rp.permission_id
    WHERE ur.tenant_id = $1
      AND ur.user_id = $2
      AND p.code = $3
    LIMIT 1
  `, [tenantId, userId, permission]);

  return result.rowCount === 1;
}

Middleware

function requirePermission(permission) {
  return async (req, res, next) => {
    const allowed = await hasPermission({
      tenantId: req.auth.tenantId,
      userId: req.auth.userId,
      permission
    });

    if (!allowed) {
      return res.status(403).json({
        code: 'FORBIDDEN',
        message: 'Acesso negado'
      });
    }

    next();
  };
}

Uso na rota

app.delete(
  '/api/projects/:id',
  authenticate,
  requirePermission('project.delete'),
  deleteProject
);

Autorização por recurso

Uma permissão geral pode não ser suficiente. O usuário pode editar projetos apenas de uma equipe:

const project = await repository.findById({
  tenantId,
  projectId
});

if (!project || project.teamId !== membership.teamId) {
  throw new ForbiddenError();
}

Não confie no frontend

Ocultar um botão melhora experiência, mas a API precisa repetir a verificação.

Permissões no token

Incluir roles ou permissions no JWT reduz consultas, mas cria atraso na revogação. Um token emitido antes da mudança continua válido até expirar.

Tokens curtos

Use access tokens de curta duração e refresh controlado. Para mudanças críticas, mantenha versão de autorização ou lista de revogação.

Permission version

{
  "sub": "user-1",
  "tenant": "tenant-1",
  "authz_version": 12
}

A API compara com a versão atual do usuário ou tenant e rejeita tokens antigos quando necessário.

Cache de permissões

authz:${tenantId}:${userId}:${version}

Inclua tenant e versão. Um cache sem contexto pode conceder acesso de outra organização.

TTL

TTL curto reduz atraso de revogação. Eventos de alteração podem invalidar imediatamente.

Default deny

Se não houver regra explícita, negue. Não use “qualquer usuário autenticado” como fallback para operações sensíveis.

Role hierarchy

Uma hierarquia pode fazer admin herdar manager e editor:

admin → manager → editor → viewer

Herança simplifica, mas pode conceder permissões inesperadas. Expanda e audite o conjunto efetivo.

Separation of duties

Algumas operações exigem funções separadas: quem cria pagamento não aprova o próprio pagamento.

Role explosion

Criar roles para cada combinação leva a dezenas ou centenas de funções. Quando regras dependem de atributos e contexto, ABAC pode complementar RBAC.

Roles customizadas

Permita que um tenant crie roles selecionando permissions permitidas. Um administrador local não deve conceder privilégios reservados ao sistema.

Permissões reservadas

system.impersonate
system.manage-tenants
billing.platform-refund

Essas permissões não aparecem no editor do cliente.

Convites

Um convite deve informar tenant, role permitida, expiração e destinatário. Ao aceitar, valide novamente quem emitiu e se ainda possui permissão.

Remoção de membro

Revogue sessões, invalide caches e interrompa jobs futuros. A remoção no banco não encerra automaticamente tokens longos.

Último administrador

Evite remover ou rebaixar o último administrador do tenant sem fluxo de transferência.

Escalada de privilégio

Um usuário com member.update não deve conseguir atribuir uma role superior à própria capacidade.

if (!actorCanGrant(targetRole)) {
  throw new ForbiddenError();
}

Mass assignment

Não aceite role, permissions ou isAdmin em um update genérico de perfil.

Multi-tenancy

Todas as associações precisam incluir tenant. O mesmo usuário pode ser admin em uma organização e viewer em outra.

Row-Level Security

RLS pode limitar linhas por tenant, enquanto RBAC decide ações. Consulte Row-Level Security no Node.js.

API Gateway

O gateway pode validar autenticação e escopos gerais, mas o serviço de domínio deve autorizar o recurso.

Service-to-service

Serviços também possuem identidades e permissions. Não reutilize uma role humana para uma aplicação.

Jobs e filas

Uma mensagem deve carregar identidade ou uma autorização derivada no momento correto. Decida se o job usa as permissões do momento do agendamento ou da execução.

Operações assíncronas

Para exportações sensíveis, revalide acesso antes de gerar e antes de disponibilizar o arquivo.

Logs de auditoria

Registre:

  • ator;
  • tenant;
  • role ou permission alterada;
  • valor anterior e novo;
  • alvo;
  • horário;
  • request ID;
  • resultado.

Não registre segredos

Auditoria deve conter a decisão, não token ou senha.

Métricas

Monitore 403, falhas por permission, mudanças de role e tentativas de escalada. Não use user ID como label de alta cardinalidade.

Observabilidade

Um log de decisão pode incluir:

{
  "authorization": "denied",
  "permission": "project.delete",
  "tenantId": "...",
  "resourceType": "project"
}

Resposta 401 ou 403?

  • 401: autenticação ausente ou inválida.
  • 403: identidade válida sem permissão.

Ocultar existência

Em recursos sensíveis, retornar 404 para um recurso fora do escopo pode reduzir enumeração. Mantenha comportamento consistente.

Testes unitários

Teste matriz de roles e permissions com casos permitidos e negados.

Teste de middleware

test('nega usuário sem project.delete', async () => {
  const response = await request(app)
    .delete('/api/projects/42')
    .set('Authorization', viewerToken);

  assert.equal(response.status, 403);
});

Teste entre tenants

Um admin do tenant A não deve acessar recursos do tenant B.

Teste de revogação

Remova a role, invalide o cache e confirme que a próxima requisição falha.

Teste de escalada

Um gerente não pode conceder admin se não possui a permission específica.

Teste de token antigo

Altere authz_version e confirme rejeição ou redução do acesso.

Testes de propriedade

Gere combinações aleatórias de roles e confira que nenhuma permission não atribuída aparece no conjunto efetivo.

Revisão periódica

Liste usuários com roles privilegiadas, roles sem uso e permissions perigosas. Remova acesso que não é mais necessário.

Erros comuns

  • Role fixa no código: mudanças ficam espalhadas.
  • Confiar no frontend: API fica exposta.
  • Permissões em token longo: revogação demora.
  • Cache sem tenant: acesso cruza organizações.
  • Update genérico de role: ocorre escalada.
  • Role explosion: modelo fica impossível de manter.
  • Sem auditoria: mudanças privilegiadas não são rastreadas.

Boas práticas

  • Modele permissions específicas.
  • Use default deny.
  • Autorize no backend.
  • Inclua tenant.
  • Cacheie com versão.
  • Use tokens curtos.
  • Proteja roles reservadas.
  • Evite escalada de privilégio.
  • Audite mudanças.
  • Teste matriz de acesso.

Conclusão

O RBAC no Node.js transforma funções organizacionais em conjuntos de permissões verificáveis. Ele funciona bem quando responsabilidades são relativamente estáveis e compreensíveis.

A implementação segura exige mais que um campo role no usuário. Tenant, recurso, revogação, cache e auditoria precisam fazer parte da decisão. Com permissions explícitas, default deny e testes de escalada, RBAC oferece autorização previsível sem depender da interface ou de tokens indefinidamente válidos.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita