Kembali ke Blog
nestjsauthenticationauthorizationrbacbackendnodejsarchitecturepassportjs

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.

4 menit baca
Solving Authorization Chaos in NestJS with RBAC

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.

Bagikan