Solving Authorization Chaos in NestJS with RBAC
Authentication itu relatif mudah. Authorization justru sering menjadi sumber masalah. Di artikel ini, kita akan membahas bagaimana mengatasi kekacauan authorization di NestJS dengan menerapkan Role-Based Access Control (RBAC) yang bersih, scalable, dan siap dipakai di project nyata—tanpa mengotori controller atau membuat arsitektur berlebihan.

Kebanyakan project NestJS dimulai dengan rapi.
Login sudah jalan, JWT sudah aman, Passport.js sudah terpasang, bahkan kadang sudah ada SSO seperti Google atau GitHub. Semua terlihat baik-baik saja.
Lalu muncul satu pertanyaan penting:
Siapa boleh melakukan apa?
Di sinilah kekacauan biasanya dimulai.
Beberapa tanda yang sering muncul:
- Logic role langsung ditulis di controller
- Perbandingan role pakai string bebas ('admin', 'superadmin')
- Logic authorization tersebar di banyak tempat
- Response error yang bikin frontend bingung
Authentication menjawab siapa kamu. Authorization menentukan apa yang boleh kamu lakukan.
Dan authorization butuh layer sendiri.
Studi Kasus Nyata yang Kita Selesaikan
Bayangkan sebuah admin dashboard internal / SaaS backoffice dengan role berikut:
- SUPER_ADMIN Akses penuh ke seluruh sistem
- ADMIN Mengelola user dan konten
- USER Akses baca saja
Ini bukan kasus aneh. Ini kasus paling umum.
Kebutuhannya jelas:
- kontrol akses di level route
- controller tetap bersih
- logic auth tidak terduplikasi
- response error ramah untuk frontend
RBAC adalah solusi paling masuk akal untuk ini.
RBAC sebagai Layer Tambahan, Bukan Rewrite
Keputusan penting yang diambil:
RBAC tidak menggantikan authentication, tapi memperluasnya.
Authentication sudah ada:
- JWT
- Passport.js
- Social login
RBAC hanya menjadi lapisan authorization di atasnya.
Pembagian tanggung jawab jadi jelas:
- Auth module → identitas user
- RBAC module → hak akses
Tidak saling campur.
Langkah 1: Role sebagai Sumber Kebenaran Tunggal
Aturan pertama: hindari magic string.
Role didefinisikan dalam enum:
export enum Role {
SUPER_ADMIN = 'super_admin',
ADMIN = 'admin',
USER = 'user',
}
Keuntungannya:
- konsisten di seluruh aplikasi
- minim typo
- mudah dikembangkan
Ini keputusan kecil, tapi dampaknya besar.
Langkah 2: Authorization Deklaratif dengan Custom Decorator
Controller seharusnya menjelaskan apa endpoint ini, bukan bagaimana validasinya.
Dengan custom decorator:
@Roles(Role.ADMIN, Role.SUPER_ADMIN)
@Get('/users')
findAllUsers() {}
Hasilnya:
- controller tetap bersih
- aturan akses mudah dibaca
- logic authorization pindah ke layer yang tepat
Langkah 3: Roles Guard sebagai Penjaga Gerbang
Validasi hak akses dilakukan di RolesGuard.
Tugasnya:
- membaca metadata dari decorator
- mengambil role user dari JWT
- memutuskan apakah request boleh lanjut atau tidak
Semua logic authorization terpusat di satu tempat.
Controller bebas dari if-else role.
Langkah 4: JWT Payload yang Bermakna
Agar RBAC efisien, role user disimpan di JWT payload:
{
"sub": "user-id",
"email": "user@mail.com",
"role": "admin"
}
Keuntungannya:
- tidak perlu query DB setiap request
- stateless
- scalable
JWT bukan sekadar token, tapi context.
Langkah 5: Merapikan Error Authorization dengan Interceptor
Default error NestJS sering seperti ini:
{
"statusCode": 403,
"message": "Forbidden resource",
"error": "Forbidden"
}
Kurang ramah untuk frontend.
Dengan custom interceptor, response diubah menjadi:
{
"code": "FORBIDDEN",
"message": "Anda tidak memiliki izin untuk mengakses resource ini"
}
Manfaatnya:
- response konsisten
- tidak bocor detail internal
- frontend lebih mudah menanganinya
Ini bukan sekadar RBAC, ini API design yang matang.
Struktur yang Jelas, Bukan Sekadar Rapi
RBAC ditempatkan di module terpisah:
/src
/auth
/rbac
├── role.enum.ts
├── roles.decorator.ts
├── roles.guard.ts
├── rbac.interceptor.ts
├── rbac.module.ts
Struktur yang jelas mencegah masalah di masa depan.
Kenapa Pendekatan Ini Scalable
Pendekatan ini:
- mudah dikembangkan ke permission-based access
- cocok untuk multi-role system
- aman untuk project production
Dan yang paling penting:
cukup bangun sekali, pakai di banyak project.
Starter Kit Tersedia di GitHub
Implementasi ini tersedia sebagai NestJs-Starter-Kits.
Jika kamu sering lelah membangun authentication dan authorization dari nol, starter kit ini dibuat agar:
- praktis
- opinionated
- siap dipakai di project nyata
👉 Silakan kunjungi repository-nya, eksplor kodenya, dan beri ⭐ jika terasa membantu. Dukungan kecil seperti itu sangat berarti untuk keberlanjutan project ini.