Role-based Access Control (RBAC) — Auth

RBAC (Role-Based Access Control) adalah model authorization di mana izin diberikan berdasarkan role (peran) pengguna, bukan per individu. Mengapa RBAC?…

RBAC (Role-Based Access Control) adalah model authorization di mana izin diberikan berdasarkan role (peran) pengguna, bukan per individu.

Mengapa RBAC? Bayangkan 100 karyawan baru bergabung. Tanpa RBAC, kamu harus mengatur izin satu per satu. Dengan RBAC, cukup assign role "karyawan" dan semua izin otomatis berlaku.

Komponen RBAC:

User → Role → Permission → Resource
  │       │        │           │
 Budi   admin    delete     article
 Ani    editor   update     article
 Cici   viewer   read       article

Implementasi sederhana:

// Definisi roles dan permissions
const ROLES = {
  admin: {
    permissions: ["create", "read", "update", "delete", "manage_users"]
  },
  editor: {
    permissions: ["create", "read", "update"]
  },
  viewer: {
    permissions: ["read"]
  }
};

// Middleware cek permission
function requirePermission(permission) {
  return (req, res, next) => {
    const userRole = req.user.role;
    const roleConfig = ROLES[userRole];

    if (!roleConfig || !roleConfig.permissions.includes(permission)) {
      return res.status(403).json({
        error: "Kamu tidak punya izin untuk melakukan ini"
      });
    }
    next();
  };
}

// Penggunaan:
app.get("/articles", requirePermission("read"), getArticles);
app.post("/articles", requirePermission("create"), createArticle);
app.delete("/articles/:id", requirePermission("delete"), deleteArticle);
app.post("/users/invite", requirePermission("manage_users"), inviteUser);

Hierarki Role: Role bisa punya hierarki — admin inherit semua permission dari editor dan viewer:

const ROLE_HIERARCHY = {
  admin: ["editor", "viewer"],
  editor: ["viewer"],
  viewer: []
};

function getAllPermissions(role) {
  const direct = ROLES[role]?.permissions || [];
  const inherited = (ROLE_HIERARCHY[role] || [])
    .flatMap(r => getAllPermissions(r));
  return [...new Set([...direct, ...inherited])];
}

// admin mendapat: manage_users + create + update + read + delete

RBAC vs ABAC:

Model Dasar Keputusan Contoh
RBAC Role user "Admin boleh hapus"
ABAC Atribut (role + context) "Author boleh edit artikel miliknya sendiri"

Untuk permission berbasis ownership, kamu butuh logika tambahan:

// ABAC-style: hanya bisa edit artikel sendiri (kecuali admin)
app.put("/articles/:id", requirePermission("update"), async (req, res) => {
  const article = await db.findArticle(req.params.id);

  if (req.user.role !== "admin" && article.authorId !== req.user.id) {
    return res.status(403).json({ error: "Hanya bisa edit artikel sendiri" });
  }

  // ... update article
});

Database schema untuk RBAC:

-- Users table
users: id, name, email, role_id

-- Roles table
roles: id, name (admin, editor, viewer)

-- Permissions table
permissions: id, name (create, read, update, delete)

-- Role-Permission pivot
role_permissions: role_id, permission_id

Best practices:

Yang akan kamu pelajari