Lindungi batas kepercayaan
Tentukan siapa yang memanggil, apa yang boleh dia lakukan, data milik siapa yang disentuh, dan seberapa banyak input yang kamu terima dari sisi yang nggak kamu percaya.
Pertanyaan
Di mana batas antara yang kamu percaya dan yang nggak, dan pemeriksaan apa yang harus terjadi tepat di batas itu?
Selesai baca ini, kamu bisa memisahkan autentikasi dari otorisasi, menerapkan isolasi tenant di setiap query, membatasi input, dan membuat API yang tetap aman kalau diserang klien yang sengaja salah pakai.
Prasyarat dan contoh
Kamu paham kontrak API (M03.01) dan sudah pernah menangani login atau token di aplikasi web.
Contoh: API multi-tenant untuk faktur: GET /invoices/{id}. Pengguna di tenant A login dengan
sah, lalu mengganti id di URL dengan id faktur milik tenant B. Server memeriksa bahwa token
valid (autentikasi lolos), mengambil faktur berdasarkan id, dan mengembalikannya. Data
tenant lain bocor, padahal nggak ada password yang dicuri. Ini kelas bug yang sering muncul
(broken object-level authorization): pemeriksaan identitas ada, pemeriksaan kepemilikan nggak.
Mekanisme
Batas kepercayaan ada di setiap tempat input masuk dari sisi yang nggak kamu kontrol: klien, pihak ketiga, bahkan layanan internal lain kalau jaringannya nggak terisolasi. Terapkan pemeriksaan di batas itu, di server, selalu.
1. Autentikasi: siapa kamu? Verifikasi kredensial (token bertanda tangan, mTLS untuk
layanan ke layanan). Periksa tanda tangan, penerbit, audiens, dan masa berlaku. Hasilnya
identitas yang tepercaya: user_id, tenant_id. Identitas ini berasal dari token yang
diverifikasi, bukan dari header atau body yang dikirim klien.
2. Otorisasi: apa yang boleh kamu lakukan, pada objek yang mana? Dua pertanyaan terpisah: bolehkah peran ini memanggil operasi ini (fungsi), dan bolehkah dia menyentuh objek ini (kepemilikan). Pemeriksaan kedua dilakukan di setiap akses objek, bukan sekali di awal.
3. Isolasi tenant di lapisan data. Jangan mengandalkan setiap developer ingat menambahkan
WHERE tenant_id = ?. Jadikan default struktural: repository yang selalu menerima konteks
tenant, atau row-level security di database. Kunci uniknya juga tercakup tenant
(UNIQUE (tenant_id, invoice_number)), dan cache key menyertakan tenant. Saat objek nggak
ditemukan di tenant pemanggil, kembalikan 404, bukan 403, supaya keberadaan objek tenant
lain nggak bocor.
4. Batas input. Tetapkan angka dan tegakkan di server:
| Batas | Contoh nilai |
| --- | --- |
| Ukuran body | 64 KB (unggahan memakai jalur khusus) |
| Panjang string | note maksimal 500 karakter |
| Ukuran size pagination | maksimal 100 |
| Kedalaman JSON dan jumlah elemen array | 5 tingkat, 1.000 elemen |
| Laju per identitas | 100 request per menit per tenant |
| Waktu eksekusi | deadline dari M03.03 |
Validasi tipe dan rentang, dan gunakan daftar nilai yang diizinkan, bukan daftar yang dilarang. Query pakai parameter terikat, bukan penggabungan string.
5. Rancang agar tahan penyalahgunaan. Anggap klien akan memakai API di luar niatmu:
- Id yang bisa ditebak (nomor urut) mempermudah enumerasi. Otorisasi tetap wajib, tapi id acak mengurangi permukaan serangan.
- Field yang nggak boleh diubah klien (
tenant_id,role,price,status) diabaikan atau ditolak, jangan di-bind otomatis dari body ke model (mass assignment). - Endpoint mahal (ekspor, pencarian dengan filter bebas) diberi kuota lebih kecil dan jalur asinkron.
- Rate limit pada login dan endpoint yang mengonfirmasi keberadaan akun.
- Log mencatat siapa, apa, dan objek mana, tanpa token atau data sensitif.
Saat rancangan ini gagal
- Mempercayai identitas dari klien. Server membaca
tenant_iddari body atau headerX-Tenant-Id. Klien mengganti nilainya dan menjadi tenant lain. - Otorisasi di UI saja. Tombol "hapus" disembunyikan untuk peran biasa, tapi endpoint
DELETEnggak memeriksa peran. - Cache melintasi tenant. Respons
/dashboarddi-cache dengan key URL saja. Tenant pertama yang memanggil mengisi cache, tenant lain menerima datanya. - Batas nggak ada. Seorang tenant memanggil
size=100000atau mengirim JSON bersarang 50.000 tingkat. Satu request menghabiskan memori dan satu tenant mengganggu semua tenant (noisy neighbor). - Kepercayaan antar layanan. Layanan internal menerima
X-User-Iddari layanan lain tanpa verifikasi, jadi siapa pun yang bisa menjangkau jaringan internal bisa menyamar. - Pesan error terlalu jujur. "Password salah untuk user ini" dan "user nggak ada" memungkinkan enumerasi akun.
Latihan
API catatan multi-tenant: GET /notes/{id}, POST /notes, GET /notes?size=N. Kamu menemukan:
(a) tenant_id dibaca dari body POST /notes; (b) GET /notes/{id} memanggil
SELECT * FROM notes WHERE id = ?; (c) size nggak dibatasi; (d) respons error 403 untuk
catatan milik tenant lain.
Untuk tiap temuan, jelaskan risikonya dan perbaikannya.
Lihat pembahasan
- (a) Klien bisa membuat catatan atas nama tenant lain, atau mengisi ruang tenant orang
lain dengan sampah. Perbaikan: ambil
tenant_iddari token terverifikasi, abaikan field itu di body (atau tolak kalau nilainya berbeda). - (b) Otorisasi objek hilang: id valid dari tenant mana pun bisa dibaca. Perbaikan:
WHERE id = ? AND tenant_id = ?, idealnya lewat repository atau row-level security supaya nggak tergantung ingatan developer. - (c)
size=10000000memaksa server membaca dan mengirim tabel besar, memakai memori dan bandwidth, dan menurunkan layanan untuk tenant lain. Perbaikan: batas maksimum (100), nilai default (20), dan tolak nilai di luar rentang dengan422. - (d)
403memberi tahu bahwa id itu ada, tapi milik orang lain. Penyerang bisa menyisir id untuk memetakan data. Perbaikan:404untuk catatan yang bukan milik tenant pemanggil, sama dengan untuk id yang memang nggak ada.
Urutan prioritas: (b) dan (a) bocor atau merusak data, jadi diperbaiki dulu. (c) dan (d) menyusul, karena dampaknya ketersediaan dan informasi.
Terkait
- Konteks tenant di key cache dibahas di M06 dan filter otorisasi pada pencarian di M11. Keduanya belum tersedia.
- M03.05 Jadikan efek idempoten memakai cakupan tenant yang sama di key idempotensi.
- Keamanan operasional yang lebih luas (rahasia, audit, respons insiden) ada di M16, belum tersedia.
- Rancangan D05 belum tersedia.
Catatan
- Asumsi: API HTTP multi-tenant dengan token terverifikasi, di belakang gateway.
- Yang nggak dibahas: protokol OAuth/OIDC secara rinci, kriptografi, dan pertahanan di tingkat jaringan seperti WAF.
- Daftar kelas bug mengikuti kategori umum seperti OWASP API Security Top 10. Nilai angka batas di tabel adalah contoh, tentukan dari beban nyata.
- Terakhir ditinjau: 26 Oktober 2026.