Kapan pakai auth.uid() dan kapan pakai auth.jwt() dalam RLS Supabase?
October 19, 2025
Bayangin kamu lagi masuk ke gedung super aman: Database Tower. Di depan setiap pintu ada satpam (RLS – Row Level Security) yang bakal nanya setiap kali kamu mau buka atau ubah data.
Satpam ini nggak bodoh, dia selalu minta bukti identitas. Nah, di Supabase, kamu bisa nunjukin dua jenis bukti:
- KTP kamu →
auth.uid() - Dompet kamu →
auth.jwt()
auth.uid() = KTP kamu
KTP isinya cuma satu hal: nomor identitas unik. Gak ada jabatan, gak ada gaji, gak ada status tim.
Kalau satpam cuma butuh tahu “apakah ini data milikmu?”, dia cukup lihat nomor KTP kamu dan cocokkan dengan data di meja resepsionis.
create policy "User can read their own profile"
on profiles
for select
to authenticated
using (auth.uid() = user_id);
Artinya:
“Kalau KTP kamu sama dengan user_id di baris ini, silakan masuk.”
Cocok dipakai untuk:
- Dashboard pribadi
- Update profil sendiri
- CRUD sederhana
- Aplikasi 1-user-1-data
Analogi: Kamu datang ke kantor pos ambil paket. Petugas cuma butuh lihat nomor KTP kamu, gak peduli kamu direktur atau anak magang.
auth.jwt() = Dompet kamu
Tapi gimana kalau satpamnya bukan cuma mau tahu siapa kamu, tapi juga mau tahu kamu kerja di tim mana dan jabatan kamu apa?
Nah, di situ kamu perlu buka dompet kamu (JWT token).
Dompet (auth.jwt()) berisi semua kartu:
- KTP (ID user)
- Kartu kerja (team_id)
- Kartu anggota (roles)
- Catatan pribadi (user_metadata)
Dari situ, satpam bisa tahu:
“Oh, kamu ternyata admin perusahaan ya? Berarti boleh masuk ke semua ruangan.”
Contohnya:
create policy "Admins can see all projects"
on projects
for select
to authenticated
using (
(auth.jwt()->'app_metadata'->'roles')::jsonb @> '["admin"]'::jsonb
);
Artinya:
“Kalau di dompetmu ada kartu bertuliskan admin, kamu boleh akses semua data.”
Cocok dipakai untuk:
- Role-based access (admin/editor)
- Multi-tenant / team system
- App dengan struktur organisasi
- Admin global
Analogi: Kamu datang ke gedung perusahaan. Satpam lihat kartu kerja di dompetmu bertuliskan “Divisi Keuangan” → kamu cuma boleh ke lantai keuangan.
Tapi hati-hati
Dompet kamu juga punya catatan pribadi (user_metadata) yang bisa kamu ubah sendiri. Misalnya kamu tulis “aku admin” di catatan pribadi, satpam gak boleh percaya itu.
Karena itu, data otorisasi sebaiknya disimpan di app_metadata,
bukan di user_metadata.
Kombinasi dua identitas
Kadang satpam harus lihat dua-duanya:
“Kalau kamu pemilik ruangan, boleh masuk. Tapi kalau kamu admin, juga boleh.”
SQL-nya bisa begini:
using (
auth.uid() = owner_id
or (auth.jwt()->'app_metadata'->>'role') = 'admin'
)
Kesimpulan:
- Pakai
auth.uid()buat cek kepemilikan data pribadi. - Pakai
auth.jwt()buat cek role, team, atau izin khusus. - Kombinasikan kalau perlu owner + admin logic.
Ringkasan
| Tujuan | Pakai | Analogi | Contoh |
|---|---|---|---|
| Biar user cuma bisa baca datanya sendiri | auth.uid() | KTP (ID unik) | auth.uid() = user_id |
| Bedakan peran (admin, editor, member) | auth.jwt() | Dompet (berisi role/team) | (auth.jwt()->'app_metadata'->>'role') = 'admin' |
| Multi-team / multi-tenant access | auth.jwt() | Kartu kerja (team_id) | team_id = (auth.jwt()->'app_metadata'->>'team_id') |
| Kombinasi owner + admin | Keduanya | Satpam lihat KTP & dompet | auth.uid() = owner_id or role='admin' |
KTP untuk RLS, Dompet untuk Permission
Kalau mau sederhana:
auth.uid()= Siapa kamuauth.jwt()= Kamu punya hak apa
RLS itu seperti pintu dengan satpam, bukan sekadar kunci. Dia gak cuma lihat token, tapi juga cek isi dompetmu sebelum ngasih akses.