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:
- Terapkan principle of least privilege — berikan izin minimal yang diperlukan
- Gunakan middleware/decorator, jangan cek permission di dalam handler
- Selalu cek authorization di server (jangan hanya sembunyikan UI)
- Log semua aksi sensitif untuk audit trail