Memahami policy engine Authentik: tipe-tipe policy, expression policy berbasis Python dengan konteks user dan request, cara binding policy ke flow, stage, dan aplikasi, logika evaluasi Any versus All, serta contoh kebijakan akses berbasis grup, jam kerja, dan alamat IP.

Di episode 5, kalian sudah membangun fondasi identitas: user, grup, dan atribut. Sekarang Authentik sudah bisa menjawab pertanyaan pertama, siapa kamu, lewat alur autentikasi. Tapi ada pertanyaan kedua yang tidak kalah penting: apa yang boleh kamu lakukan setelah masuk?
Jawabannya ada di policy — conditional logic yang menentukan keputusan ya atau tidak di hampir setiap titik penting Authentik. Analoginya begini: authentication seperti penjaga di lobi gedung yang memeriksa kartu identitas, sedangkan policy adalah daftar ruangan yang boleh dimasuki, lengkap dengan jam buka dan aturan khusus per lantai. Di episode ini kalian akan belajar memprogram daftar ruangan itu.
Secara sederhana, policy adalah keputusan boolean: lulus (pass) atau gagal (fail). Keputusan inilah yang kemudian menggerakkan logika Authentik. Ada lima tempat utama policy bisa di-bind (dilampirkan):
Selain policy, kalian juga bisa meng-bind user atau grup secara langsung ke target yang sama. Binding langsung ini dievaluasi sebagai pemeriksaan keanggotaan sederhana — berguna saat kalian hanya butuh aturan izinkan atau tolak tanpa membuat objek policy baru.
Tip
Aturan praktis dari dokumentasi Authentik: gunakan binding grup langsung jika keputusannya statis (misal "hanya grup admins"), dan gunakan policy ketika keputusan bergantung pada konteks runtime seperti jaringan, source, data prompt, atau riwayat request.
Authentik menyediakan beberapa tipe policy bawaan yang bisa dipakai tanpa menulis kode:
Untuk sebagian besar kebutuhan otorisasi, expression policy adalah pilihan utama — justru karena ia bisa menggabungkan semua kondisi di atas dalam satu ekspresi.
Expression policy adalah potongan kode Python yang dieksekusi di sisi server Authentik saat policy dievaluasi. Ekspresi menerima konteks kaya, lalu mengembalikan True jika lulus atau False jika gagal. Contoh paling umum: menolak akses jika user bukan anggota grup tertentu.
if ak_is_group_member(request.user, name="app-admins"):
return True
ak_message("Akses ditolak: kamu bukan anggota grup app-admins")
return FalsePerhatikan dua hal di atas. Pertama, helper ak_is_group_member(user, name="...") memeriksa keanggotaan grup dengan bersih. Kedua, ak_message("...") mengisi pesan yang akan ditampilkan ke user ketika policy gagal — jangan biarkan user menebak sendiri alasan penolakannya.
Important
Expression policy adalah kode Python yang berjalan dengan hak istimewa tinggi di dalam server Authentik. Perlakukan kemampuan membuat atau mengeditnya seperti memberikan akses administrator. Jangan menyalin ekspresi dari sumber yang tidak dipercaya.
Beberapa variabel dan helper yang paling sering dipakai:
request.user: user yang sedang dievaluasi terhadap policy ini.request.context: dictionary berisi data dinamis dari eksekusi flow.ak_is_group_member(user, name="..."): cek keanggotaan grup.ak_user_has_authenticator(user): cek apakah user punya perangkat MFA.ak_message("..."): set pesan yang terlihat user.ak_client_ip: objek IP klien yang sudah di-parse, cocok untuk cek jaringan.regex_match(value, pattern) dan regex_replace(value, pattern, repl): manipulasi string.Satu jebakan klasik: ketika policy berjalan di dalam flow autentikasi, request.user belum tentu user yang sedang login — bisa saja masih AnonymousUser sampai sebuah stage user login menetapkannya. Untuk kasus ini, dokumentasi menyarankan membaca pending_user dari flow context (misalnya request.context.get("pending_user")) agar keputusan memakai identitas yang benar.
Policy yang di-bind ke target yang sama dievaluasi berurutan dari atas ke bawah (ascending order). Ini penting saat membaca log maupun saat beberapa policy menghasilkan pesan untuk user.
Selain urutan, setiap target binding memiliki Policy engine mode:
Ada juga beberapa pengaturan tambahan yang sering menyelamatkan waktu kalian di produksi:
Warning
Defaultnya, jika sebuah target tidak punya binding sama sekali, Authentik menganggapnya lulus. Jika kalian mengamankan aplikasi sensitif, jangan biarkan aturan akses bergantung pada ketiadaan policy — dan pilih failure result yang fail closed untuk ekspresi yang melindungi sesuatu yang penting.
Policy di awal episode ini sudah menunjukkan polanya: tolak jika bukan anggota grup app-admins. Binding ke application berarti aplikasi hanya bisa dibuka anggota grup tersebut.
Ingin layanan hanya bisa diakses jam kerja? Cukup bandingkan jam saat evaluasi berlangsung.
from datetime import datetime
now = datetime.now()
return 9 <= now.hour < 17Untuk layanan internal yang seharusnya hanya bisa diakses dari jaringan kantor, gunakan perbandingan jaringan.
from ipaddress import ip_network
return ak_client_ip in ip_network("10.0.0.0/24")Ini pola yang paling banyak dipakai: bind sebuah policy ke stage binding, sehingga stage tertentu — misalnya authenticator validate — hanya berjalan untuk sebagian user atau aplikasi. Persis inilah yang akan kalian bedah lebih dalam di episode 7 tentang MFA.
Jangan pernah mengandalkan tebakan. Authentik menyediakan alat untuk menguji policy sebelum dipakai:
ak_message.Tip
Kembangkan kebiasaan menguji dengan user contoh yang mewakili tiap peran: satu user admin, satu user biasa, dan satu user yang seharusnya ditolak. Tiga uji ini sudah menangkap sebagian besar kesalahan logika.
Poin kunci episode ini:
request.user dan request.context plus helper seperti ak_is_group_member.Sekarang kalian sudah bisa memprogram logika "siapa boleh masuk". Tapi masih ada pertanyaan menggoda: bagaimana kalau kondisi itu berbunyi "semua admin wajib MFA"? Di episode 7, kalian akan membedah authentication stages dan mekanisme Multi-Factor Authentication — mulai dari identification, password, sampai authenticator validate — beserta cara binding-nya ke aplikasi.