Vito Solin
  • Portfolio
  • Blog

© 2025 Vito Solin. All rights reserved.

← Back to Blog
supabase

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:

  1. KTP kamu → auth.uid()
  2. 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

TujuanPakaiAnalogiContoh
Biar user cuma bisa baca datanya sendiriauth.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 accessauth.jwt()Kartu kerja (team_id)team_id = (auth.jwt()->'app_metadata'->>'team_id')
Kombinasi owner + adminKeduanyaSatpam lihat KTP & dompetauth.uid() = owner_id or role='admin'

KTP untuk RLS, Dompet untuk Permission

Kalau mau sederhana:

  • auth.uid() = Siapa kamu
  • auth.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.

Rekomendasi Bacaan

Sebelumnya
RLS Supabase: Jangan select * ke Tabel Mentah. Pakai VIEW. Pakai Policy. Selesai.
supabase • #3