Chapter Policy RLS berakhir pada satu pertanyaan yang belum terjawab: policy dan GRANT semuanya mengecek nama role, jadi bagaimana sebuah koneksi membuktikan bahwa dirinya memang benar budi_tmj dan bukan peniru? Jawabannya terjadi sebelum satu baris SQL pun dieksekusi. Begitu klien membuka koneksi, PostgreSQL menjalankan proses authentication — pemeriksaan identitas yang memutuskan pengklaim nama role layak masuk atau tidak. Keputusannya tidak diambil oleh SQL, melainkan oleh file konfigurasi pg_hba.conf yang memasangkan setiap kombinasi koneksi dengan satu metode pemeriksaan. Server latihan kita memakai metode trust lewat unix socket sehingga seluruh latihan berjalan tanpa sandi — dan keputusan itu sendiri akan kita buktikan nyatanya di chapter ini, karena justru metode inilah yang paling berbahaya bila terpasang di produksi.

Di Mana Keputusan Authentication Diambil #

PostgreSQL tidak punya satu jawaban tunggal untuk “bagaimana cara login”. Setiap koneksi dinilai satu per satu: dari mana koneksi datang (unix socket atau TCP), database mana yang diminta, dan nama role yang diklaim. Ketiganya dicocokkan terhadap daftar aturan di file pg_hba.conf; aturan yang cocok menentukan metode pemeriksaan — bisa trust yang langsung percaya, scram-sha-256 yang menuntut sandi, peer yang bertanya ke sistem operasi, atau reject yang menolak tanpa negosiasi. Detail penulisan file itu adalah bahasan chapter pg_hba.conf ; chapter ini membedah isi metodenya sendiri: cara kerja tiap metode, bagaimana sandi disimpan di server, dan bagaimana identitas hasil pemeriksaan itu terlihat dari dalam SQL.

Peta Metode Authentication #

Daftar lengkap metode resmi cukup panjang, tetapi delapan berikut menutupi hampir semua kasus nyata:

MetodeCara memeriksa identitasCatatan pemakaian
trustTidak memeriksa apa pun — nama role dipercaya begitu sajaLatihan lokal dan mesin terisolasi; berbahaya di produksi
rejectSelalu menolak koneksiMemblokir kombinasi tertentu tanpa menghapus aturan lain
passwordMengirim sandi sebagai teks polosButuh TLS; praktiknya dihindari — tidak ada alasan memilihnya
md5Challenge-response dengan hash md5Warisan lama sebelum PostgreSQL 14; tidak bisa memverifikasi sandi SCRAM
scram-sha-256Challenge-response SCRAM dengan SHA-256Metode sandi yang direkomendasikan; bawaan sejak PostgreSQL 14
peerBertanya nama pengguna OS pemilik koneksi unix socketHanya untuk local; cocok untuk admin di mesin yang sama
certMemeriksa sertifikat TLS klienKoneksi harus TLS; dibahas di TLS dan Koneksi Aman
gss / sspiDelegasi ke Kerberos / SSPISSO perusahaan; sspi adalah padanannya di Windows

Tiga metode sandi di tengah tabel itu membentuk garis sejarah: password mengirim sandi apa adanya, md5 menyembunyikannya lewat hash, dan scram-sha-256 menuntut lebih lagi — server tidak pernah menyimpan bahan untuk menyusun ulang sandinya. Untuk instalasi baru, pilihan selain scram-sha-256 untuk autentikasi berbasis sandi sulit dibenarkan.

Trust: Praktis untuk Latihan, Berbahaya untuk Produksi #

Metode trust memutuskan bahwa nama role yang diklaim klien adalah kebenaran. Tidak ada sandi, tidak ada bukti — siapa pun yang bisa menjangkau socket atau alamat yang diizinkan masuk sebagai role manapun yang ia sebut, termasuk superuser. Server latihan kita memakai trust sehingga psql terhubung tanpa sekali pun dimintai sandi. File berikut membuktikannya secara nyata: kita membuat role budi_um lengkap dengan sandi, lalu membuka koneksi baru sebagai budi_um tanpa memasukkan sandi itu sama sekali:

-- Server latihan memakai metode trust lewat unix socket:
-- koneksi tidak diperiksa sandinya sama sekali. File ini
-- membuktikannya dengan membuka koneksi baru sebagai budi_um
-- tanpa memasukkan sandi.
DROP ROLE IF EXISTS budi_um;

CREATE ROLE budi_um LOGIN PASSWORD 'sandi_latihan_budi';

-- \connect membuka koneksi baru sebagai budi_um.
-- Dengan metode trust, psql tidak akan meminta sandi.
\connect postgres budi_um

SELECT current_user;

-- Kembali sebagai postgres untuk melanjutkan latihan.
\connect postgres postgres

Output yang Dihasilkan:

text
DROP ROLE
CREATE ROLE
You are now connected to database "postgres" as user "budi_um".
 current_user 
--------------
 budi_um
(1 row)

You are now connected to database "postgres" as user "postgres".

Mari kita bedah baris-baris pentingnya:

  1. CREATE ROLE budi_um LOGIN PASSWORD 'sandi_latihan_budi' — role dibuat dengan atribut LOGIN dan sebuah sandi. Sandi ini tersimpan di server, tetapi metode trust tidak peduli: sandi sama sekali tidak diperiksa saat koneksi.
  2. \connect postgres budi_um — perintah meta psql ini membuka koneksi baru ke database postgres dengan role budi_um. Bila metode yang berlaku adalah scram-sha-256, psql akan berhenti dan meminta sandi; dengan trust, koneksi langsung terbuka.
  3. SELECT current_user — hasilnya budi_um membuktikan koneksi baru itu benar-benar berjalan dengan identitas role tersebut, tanpa satu kredensial pun dipertukarkan.

Menyimpan Sandi: password_encryption dan pg_authid #

Kebalikan dari trust, metode berbasis sandi menuntut server menyimpan bahan verifikasi. Algoritma penyimpanannya diatur parameter password_encryption, dan verifier hasilnya disimpan di catalog pg_authid — catalog yang hanya bisa dibaca superuser. File berikut menelusuri keduanya, termasuk membuktikan bahwa parameter itu bisa diganti per sesi dan mengubah bentuk sandi yang tersimpan:

-- Sandi dari sisi server: parameter password_encryption menentukan
-- algoritma penyimpanan, catalog pg_authid menyimpan verifier-nya.
SHOW password_encryption;

-- trust aktif, jadi sandi tidak diperiksa saat koneksi -- tetapi
-- tetap disimpan untuk dipakai saat server berganti metode.
ALTER ROLE budi_um PASSWORD 'sandi_latihan_budi';

SELECT rolname,
       CASE WHEN rolpassword LIKE 'SCRAM-SHA-256%' THEN 'SCRAM-SHA-256'
            WHEN rolpassword LIKE 'md5%'           THEN 'md5'
            ELSE 'lainnya' END                     AS skema_hash,
       split_part(split_part(rolpassword, '$', 2), ':', 1) AS iterasi
FROM pg_authid
WHERE rolname = 'budi_um';

-- password_encryption bisa diganti per sesi: sandi yang disimpan
-- berikutnya ikut metode baru. Di sini kita sengaja memakai md5
-- yang lama supaya perbedaannya terlihat.
SET password_encryption = 'md5';

ALTER ROLE budi_um PASSWORD 'sandi_latihan_budi';

SELECT rolname,
       CASE WHEN rolpassword LIKE 'SCRAM-SHA-256%' THEN 'SCRAM-SHA-256'
            WHEN rolpassword LIKE 'md5%'           THEN 'md5'
            ELSE 'lainnya' END                     AS skema_hash
FROM pg_authid
WHERE rolname = 'budi_um';

-- Kembali ke metode bawaan lalu simpan ulang sandinya.
RESET password_encryption;

ALTER ROLE budi_um PASSWORD 'sandi_latihan_budi';

SELECT rolname,
       CASE WHEN rolpassword LIKE 'SCRAM-SHA-256%' THEN 'SCRAM-SHA-256'
            WHEN rolpassword LIKE 'md5%'           THEN 'md5'
            ELSE 'lainnya' END                     AS skema_hash,
       split_part(split_part(rolpassword, '$', 2), ':', 1) AS iterasi
FROM pg_authid
WHERE rolname = 'budi_um';

-- Masa berlaku sandi: setelah tanggal ini, koneksi yang memakai
-- sandi untuk budi_um ditolak server.
ALTER ROLE budi_um VALID UNTIL '2027-06-30';

SELECT rolname, rolvaliduntil
FROM pg_roles
WHERE rolname = 'budi_um';

Output yang Dihasilkan:

text
 password_encryption 
---------------------
 scram-sha-256
(1 row)

ALTER ROLE
 rolname |  skema_hash   | iterasi 
---------+---------------+---------
 budi_um | SCRAM-SHA-256 | 4096
(1 row)

SET
ALTER ROLE
 rolname | skema_hash 
---------+------------
 budi_um | md5
(1 row)

RESET
ALTER ROLE
 rolname |  skema_hash   | iterasi 
---------+---------------+---------
 budi_um | SCRAM-SHA-256 | 4096
(1 row)

ALTER ROLE
 rolname |     rolvaliduntil      
---------+------------------------
 budi_um | 2027-06-30 00:00:00+07
(1 row)

Empat fakta dari hasil eksekusi file itu:

  1. SHOW password_encryption — nilainya scram-sha-256, bawaan sejak PostgreSQL 14; instalasi baru tidak perlu mengaturnya ulang.
  2. Query pg_authid pertama — verifier tersimpan dengan awalan SCRAM-SHA-256 dan iterasi bernilai 4096. Nilai rolpassword dipotong dengan split_part karena bagian salt dan kunci di belakangnya acak — berubah setiap kali sandi disimpan ulang.
  3. SET password_encryption = 'md5' — pergantian per sesi ini membuat ALTER ROLE ... PASSWORD berikutnya tersimpan sebagai md5, terbukti pada query kedua. Setelah RESET, penyimpanan kembali ke SCRAM — perilaku yang menjelaskan mengapa server warisan lama bisa terkunci di format lemah.
  4. ALTER ROLE budi_um VALID UNTIL '2027-06-30' — kolom rolvaliduntil pada pg_roles mencatat masa berlaku sandi; lewat tanggal itu, koneksi berbasis sandi untuk role tersebut ditolak. Cocok untuk akun sementara dan kontraktor.

Perhatikan juga bahwa sandi tetap tersimpan rapi meskipun kita terhubung lewat trust — koneksi dan penyimpanan sandi adalah dua urusan terpisah. Role yang hari ini dipakai di server latihan tanpa sandi sudah siap menjadi role ber-sandi begitu pg_hba.conf diganti metodenya.

Cara Kerja scram-sha-256 #

Keunggulan scram-sha-256 dibanding metode sandi sebelumnya ada pada dua sifatnya: sandi tidak pernah dikirim ke server, dan server tidak menyimpan bahan untuk menyusun ulang sandi. Yang tersimpan di pg_authid hanyalah verifier — turunan matematis satu arah dari sandi. Pertukarannya berjalan sebagai challenge-response:

Diagram di atas merangkum protokol SCRAM dalam bentuk paling sederhana. Klien mengirim identitas dan sebuah angka acak (nonce); server membalas dengan salt dan jumlah iterasi yang diambil dari verifier tersimpan; klien menghitung bukti kepemilikan sandi secara lokal dan mengirim buktinya — bukan sandinya; terakhir server membandingkan bukti itu dengan verifier di pg_authid. Penyadap jaringan hanya melihat nama role, salt, nonce, dan bukti yang berbeda setiap sesi. Konsekuensi praktisnya: server yang bocor (misalnya backup pg_authid dicuri) tetap tidak membocorkan sandi aslinya, dan sandi yang sama pada dua server menghasilkan verifier berbeda karena salt-nya berbeda.

session_user vs current_user #

Identitas hasil authentication bisa diamati dari dalam SQL. PostgreSQL membedakan dua fungsi: session_user adalah role yang lolos pemeriksaan authentication saat koneksi dibuka, sedangkan current_user adalah identitas efektif saat ini — yang bisa berganti lewat SET ROLE sebagaimana sering kita pakai di chapter-chapter sebelumnya. File singkat berikut menunjukkan keduanya berpisah:

-- session_user = identitas hasil authentication (siapa yang login);
-- current_user = identitas efektif saat ini (bisa berubah lewat SET ROLE).
SELECT session_user, current_user;

SET ROLE budi_um;

SELECT session_user, current_user;

RESET ROLE;

Output yang Dihasilkan:

text
 session_user | current_user 
--------------+--------------
 postgres     | postgres
(1 row)

SET
 session_user | current_user 
--------------+--------------
 postgres     | budi_um
(1 row)

RESET

Baris pertama memperlihatkan keduanya bernilai postgres — kita memang terhubung sebagai postgres. Setelah SET ROLE budi_um, current_user berganti menjadi budi_um sementara session_user tetap postgres: pemeriksaan authentication hanya terjadi sekali per koneksi, dan SET ROLE adalah operasi otorisasi di dalam sesi, bukan autentikasi ulang. Bagi audit, session_user menjawab “siapa yang membuka koneksi ini” — pertanyaan yang tidak bisa dijawab current_user.

Metode per Jenis Koneksi #

pg_hba.conf memasangkan metode dengan jenis koneksi. Baris local mengatur koneksi lewat unix socket — jalur tanpa jaringan yang dipakai psql di mesin yang sama; baris host mengatur TCP, dengan variasi hostssl yang mensyaratkan TLS dan hostnossl yang justru melarangnya. Metode peer hanya tersedia untuk local karena bertanya langsung ke sistem operasi: nama pengguna OS pemilik proses klien harus sama dengan nama role yang diklaim. Contoh tampilan umum file di server produksi:

text
# TYPE      DATABASE    USER        ADDRESS         METHOD
local       all         postgres                    peer
local       all         all                         scram-sha-256
host        penjualan   app_web     10.0.0.0/24     scram-sha-256
hostssl     penjualan   app_laporan 0.0.0.0/0       scram-sha-256
host        all         all         0.0.0.0/0       reject

Konfigurasi di atas memakai peer untuk admin di mesin yang sama, scram-sha-256 untuk unix socket biasa dan untuk subnet aplikasi, hostssl untuk subnet yang wajib TLS, dan reject sebagai penutup yang menolak sisanya. Setiap penyuntingan pg_hba.conf baru berlaku setelah server memuat ulang konfigurasinya — misalnya lewat pg_ctl reload -D /path/ke/pgdata dari shell, atau lewat SQL dengan SELECT pg_reload_conf(); oleh superuser — tanpa memutus koneksi yang sedang berjalan.

File penutup chapter ini membersihkan role latihan:

-- Pembersihan role latihan chapter authentication.
DROP OWNED BY budi_um;

DROP ROLE budi_um;

SELECT count(*) AS sisa_role_latihan
FROM pg_roles
WHERE rolname = 'budi_um';

Output yang Dihasilkan:

text
DROP OWNED
DROP ROLE
 sisa_role_latihan 
-------------------
                 0
(1 row)

Metode authentication kini terpetakan: trust untuk latihan, scram-sha-256 untuk produksi, peer untuk admin lokal, cert menanti chapter TLS. Semua metode itu dipanggil oleh nama dari satu tempat — baris-baris pg_hba.conf yang memutuskan kombinasi mana dijawab dengan metode mana. Chapter berikutnya membedah file tersebut baris demi baris: format kolomnya, urutan pencocokannya yang membuat aturan pertama selalu menang, dan cara membaca kembali aturan aktif lewat view pg_hba_file_rules.

Referensi #

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

bersihkan-auth.sql

Unduh berkas
sql
-- Pembersihan role latihan chapter authentication.
DROP OWNED BY budi_um;

DROP ROLE budi_um;

SELECT count(*) AS sisa_role_latihan
FROM pg_roles
WHERE rolname = 'budi_um';

login-tanpa-sandi.sql

Unduh berkas
sql
-- Server latihan memakai metode trust lewat unix socket:
-- koneksi tidak diperiksa sandinya sama sekali. File ini
-- membuktikannya dengan membuka koneksi baru sebagai budi_um
-- tanpa memasukkan sandi.
DROP ROLE IF EXISTS budi_um;

CREATE ROLE budi_um LOGIN PASSWORD 'sandi_latihan_budi';

-- \connect membuka koneksi baru sebagai budi_um.
-- Dengan metode trust, psql tidak akan meminta sandi.
\connect postgres budi_um

SELECT current_user;

-- Kembali sebagai postgres untuk melanjutkan latihan.
\connect postgres postgres

sesi-vs-role.sql

Unduh berkas
sql
-- session_user = identitas hasil authentication (siapa yang login);
-- current_user = identitas efektif saat ini (bisa berubah lewat SET ROLE).
SELECT session_user, current_user;

SET ROLE budi_um;

SELECT session_user, current_user;

RESET ROLE;

simpan-sandi.sql

Unduh berkas
sql
-- Sandi dari sisi server: parameter password_encryption menentukan
-- algoritma penyimpanan, catalog pg_authid menyimpan verifier-nya.
SHOW password_encryption;

-- trust aktif, jadi sandi tidak diperiksa saat koneksi -- tetapi
-- tetap disimpan untuk dipakai saat server berganti metode.
ALTER ROLE budi_um PASSWORD 'sandi_latihan_budi';

SELECT rolname,
       CASE WHEN rolpassword LIKE 'SCRAM-SHA-256%' THEN 'SCRAM-SHA-256'
            WHEN rolpassword LIKE 'md5%'           THEN 'md5'
            ELSE 'lainnya' END                     AS skema_hash,
       split_part(split_part(rolpassword, '$', 2), ':', 1) AS iterasi
FROM pg_authid
WHERE rolname = 'budi_um';

-- password_encryption bisa diganti per sesi: sandi yang disimpan
-- berikutnya ikut metode baru. Di sini kita sengaja memakai md5
-- yang lama supaya perbedaannya terlihat.
SET password_encryption = 'md5';

ALTER ROLE budi_um PASSWORD 'sandi_latihan_budi';

SELECT rolname,
       CASE WHEN rolpassword LIKE 'SCRAM-SHA-256%' THEN 'SCRAM-SHA-256'
            WHEN rolpassword LIKE 'md5%'           THEN 'md5'
            ELSE 'lainnya' END                     AS skema_hash
FROM pg_authid
WHERE rolname = 'budi_um';

-- Kembali ke metode bawaan lalu simpan ulang sandinya.
RESET password_encryption;

ALTER ROLE budi_um PASSWORD 'sandi_latihan_budi';

SELECT rolname,
       CASE WHEN rolpassword LIKE 'SCRAM-SHA-256%' THEN 'SCRAM-SHA-256'
            WHEN rolpassword LIKE 'md5%'           THEN 'md5'
            ELSE 'lainnya' END                     AS skema_hash,
       split_part(split_part(rolpassword, '$', 2), ':', 1) AS iterasi
FROM pg_authid
WHERE rolname = 'budi_um';

-- Masa berlaku sandi: setelah tanggal ini, koneksi yang memakai
-- sandi untuk budi_um ditolak server.
ALTER ROLE budi_um VALID UNTIL '2027-06-30';

SELECT rolname, rolvaliduntil
FROM pg_roles
WHERE rolname = 'budi_um';