Basic Auth #
Dalam mengamankan sistem web, sering kali kita membutuhkan pembatasan akses cepat tanpa harus menulis kode autentikasi yang rumit di sisi aplikasi backend. Misalnya, untuk melindungi dashboard pemantauan (monitoring dashboard seperti Prometheus/Grafana), halaman dokumentasi API internal, panel admin CMS, atau lingkungan penayangan sementara (staging environment).
Salah satu cara tertua, paling sederhana, namun sangat efektif jika diterapkan dengan benar adalah HTTP Basic Authentication (atau biasa disebut Basic Auth). Nginx mendukung Basic Auth secara native melalui modul bawaan ngx_http_auth_basic_module. Di artikel ini, kita akan membedah secara mendalam bagaimana Basic Auth bekerja di tingkat protokol, cara membuat berkas kredensial menggunakan utilitas htpasswd dengan enkripsi modern, konfigurasi pembatasan akses di Nginx, penggabungan dengan kontrol IP menggunakan logika satisfy, serta memahami batasan keamanan dari metode ini sebelum melangkah ke solusi yang lebih canggih.
Bagaimana HTTP Basic Authentication Bekerja? #
HTTP Basic Auth adalah bagian dari spesifikasi protokol HTTP standar (RFC 7617). Mekanisme ini tidak memerlukan cookies, session di server, atau form login HTML kustom. Seluruh proses dialog login ditangani langsung oleh browser pengguna.
Berikut adalah diagram alur proses jabat tangan (handshake) HTTP Basic Auth:
sequenceDiagram
autonumber
actor Browser as Browser (Client)
actor Server as Nginx Server
Browser->>Server: HTTP GET /admin/ (Tanpa Kredensial)
Server->>Browser: HTTP 401 Unauthorized (Header: WWW-Authenticate)
Note over Browser: Browser membaca header & memunculkan dialog popup login
Note over Browser: Pengguna memasukkan username & password
Browser->>Server: HTTP GET /admin/ (Header: Authorization: Basic Base64)
Note over Server: Nginx mendecode Base64 & mencocokkan dengan file .htpasswd
Server->>Browser: HTTP 200 OK (Halaman Admin Terbuka)Penjelasan Detail Langkah Alur: #
- Langkah 1: Pengguna mencoba mengakses area terproteksi (misalnya
/admin/) tanpa mengirimkan informasi login apa pun. - Langkah 2: Nginx mendeteksi bahwa area tersebut memerlukan autentikasi. Nginx menolak request dengan mengirimkan status
HTTP 401 Unauthorizeddisertai header responsWWW-Authenticate: Basic realm="Nama Realm". Parameterrealmadalah string teks yang menjelaskan area apa yang sedang diakses. - Langkah 3: Browser menangkap status 401 dan header
WWW-Authenticate, lalu menghentikan render halaman dan menampilkan kotak dialog popup bawaan browser yang meminta username dan password. - Langkah 5: Setelah pengguna menekan tombol login, browser mengirimkan kembali request HTTP GET yang sama, tetapi kali ini menyisipkan header
Authorization: Basic [kredensial_base64].- Penting: Kredensial tersebut diformat sebagai
username:passwordlalu dikodekan menggunakan Base64. Sebagai contoh, jika username adalahadmindan password adalahsandi123, string aslinya adalahadmin:sandi123. Hasil pengodean Base64-nya adalahYWRtaW46c2FuZGkxMjM=. - Header yang dikirimkan berbunyi:
Authorization: Basic YWRtaW46c2FuZGkxMjM=.
- Penting: Kredensial tersebut diformat sebagai
- Langkah 6: Nginx menerima header tersebut, mendekode string Base64 untuk mendapatkan username dan password asli, lalu mencocokkan hash password-nya dengan daftar yang ada di dalam berkas konfigurasi kredensial server kita.
- Langkah 7: Jika cocok, Nginx mengizinkan request masuk dan mengembalikan halaman web dengan status
HTTP 200 OK.
[!WARNING] Karena pengodean Base64 bukanlah enkripsi, string
YWRtaW46c2FuZGkxMjM=sangat mudah didekode kembali menjadi teks biasa oleh siapa saja yang menyadap jaringan. Oleh karena itu, HTTP Basic Auth wajib dijalankan di atas HTTPS. Jika dijalankan di atas HTTP biasa, kredensial pengguna akan bocor secara instan di jaringan Wi-Fi publik atau ISP.
Panduan Membuat File Kredensial dengan htpasswd #
Untuk menyimpan daftar username dan password yang sah, Nginx menggunakan format berkas yang sama dengan berkas .htpasswd milik Apache. Kita akan menggunakan perkakas baris perintah bernama htpasswd untuk mengelolanya.
Langkah 1: Instalasi Perkakas Apache2 Utils #
Utilitas htpasswd dibundel di dalam paket utilitas Apache. Jalankan perintah berikut untuk menginstalnya:
# Di Ubuntu / Debian
sudo apt update
sudo apt install apache2-utils -y
# Di CentOS / Rocky Linux / RHEL
sudo dnf install httpd-tools -y
Langkah 2: Membuat File Kredensial Baru #
Kita disarankan menyimpan berkas kredensial ini di luar direktori dokumen web publik (web root) agar tidak bisa diunduh oleh publik. Direktori terbaik adalah di /etc/nginx/.
Mari kita buat berkas password baru dengan memasukkan user pertama (misalnya admin_user):
# Flag -c digunakan untuk CREATE (membuat berkas baru)
# PERINGATAN: Flag -c akan menghapus file lama jika file tersebut sudah ada!
sudo htpasswd -B -c /etc/nginx/.htpasswd admin_user
- Pentingnya Flag
-B: Secara default,htpasswdpada beberapa sistem operasi menggunakan algoritma MD5 (apr1) atau Crypt yang memiliki tingkat keamanan rendah menurut standar modern. Dengan menambahkan flag-B, kita memaksahtpasswdmenggunakan algoritma bcrypt. Bcrypt jauh lebih aman karena menggunakan mekanisme perlambatan (work factor) untuk menangkal serangan pencocokan kata sandi massal (brute-force). - Setelah menekan enter, terminal akan meminta kita memasukkan password untuk user tersebut sebanyak dua kali. Password tidak akan ditampilkan di layar selama pengetikan.
Langkah 3: Menambah atau Menghapus User Tambahan #
Jika kita ingin menambahkan user kedua atau ketiga ke dalam file yang sudah ada, jangan gunakan flag -c, karena hal itu akan menghapus user pertama yang telah kita buat sebelumnya. Cukup ketik perintah tanpa flag -c:
# Tambah user kedua (tanpa -c)
sudo htpasswd -B /etc/nginx/.htpasswd staff_user
# Menghapus user dari file
sudo htpasswd -D /etc/nginx/.htpasswd staff_user
Langkah 4: Memeriksa Isi Berkas Kredensial #
Kita bisa menginspeksi isi berkas .htpasswd menggunakan perintah cat. Kredensial disimpan dalam format satu user per baris dengan format username:hash_password:
cat /etc/nginx/.htpasswd
Outputnya akan terlihat seperti ini:
admin_user:$2y$05$Lw8YwzD2Y.rJgZp...
Perhatikan teks $2y$ di awal hash password. Ini menandakan bahwa password dienkripsi menggunakan algoritma bcrypt yang aman.
Langkah 5: Memperketat Hak Akses Berkas (File Permissions) #
Nginx perlu membaca file .htpasswd untuk melakukan verifikasi, tetapi pengguna sistem lain di server kita tidak boleh membacanya. Mari kita atur kepemilikan file ke user root dan grup server Nginx (biasanya www-data atau nginx), serta batasi hak aksesnya:
# Ubah pemilik ke root dan grup ke www-data (sesuaikan grup di OS Anda)
sudo chown root:www-data /etc/nginx/.htpasswd
# Batasi hak akses: Pemilik boleh baca/tulis, grup boleh baca, lainnya tidak boleh sama sekali
sudo chmod 640 /etc/nginx/.htpasswd
Konfigurasi Basic Auth di Nginx #
Setelah berkas kredensial siap, kita dapat menerapkan proteksi di konfigurasi virtual host Nginx. Kita menggunakan dua direktif utama:
auth_basic: Mengaktifkan autentikasi dan menentukan teks deskripsi (realm) yang muncul di dialog browser.auth_basic_user_file: Menentukan jalur mutlak (absolute path) ke berkas.htpasswdyang telah kita buat.
Skenario 1: Melindungi Seluruh Situs Web #
Jika kita ingin seluruh konten domain (termasuk halaman utama dan seluruh aset) dikunci dengan password, kita meletakkan direktif di tingkat blok server:
server {
listen 443 ssl;
server_name staging.example.com;
ssl_certificate /etc/letsencrypt/live/staging.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/staging.example.com/privkey.pem;
# Proteksi seluruh situs
auth_basic "Staging Environment - Kredensial Wajib";
auth_basic_user_file /etc/nginx/.htpasswd;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Skenario 2: Melindungi Lokasi / Direktori Spesifik #
Sering kali kita hanya ingin melindungi area tertentu saja (misalnya folder administrasi /admin/ atau dashboard internal /dashboard/), sementara halaman utama situs tetap dapat diakses bebas oleh publik. Kita meletakkan direktif di dalam blok location yang spesifik:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
root /var/www/html;
index index.html;
# Halaman publik - BEBAS AKSES
location / {
try_files $uri $uri/ =404;
}
# Halaman admin - TERPROTEKSI
location /admin/ {
auth_basic "Panel Administrator";
auth_basic_user_file /etc/nginx/.htpasswd;
# Pastikan php atau proxy_pass di dalamnya juga mewarisi proteksi ini
try_files $uri $uri/ =404;
}
}
Skenario 3: Mematikan Basic Auth untuk Sub-Direktori Tertentu (auth_basic off)
#
Jika kita telah mengaktifkan Basic Auth di tingkat server block (seluruh situs terkunci), namun kita membutuhkan satu sub-direktori tertentu (misalnya folder aset gambar publik /images/ atau endpoint webhook /webhook/ dari sistem luar) agar bebas diakses tanpa password, kita bisa mematikan Basic Auth di location block bersangkutan dengan memberikan nilai off:
server {
listen 443 ssl;
server_name app.example.com;
# Aktif secara global di seluruh server block
auth_basic "Aplikasi Terbatas";
auth_basic_user_file /etc/nginx/.htpasswd;
# Endpoint ini ikut terkunci otomatis karena pewarisan
location / {
proxy_pass http://localhost:3000;
}
# Endpoint khusus Webhook API - BEBAS AKSES (Basic Auth dimatikan)
location /api/webhook {
auth_basic off; # Mematikan pewarisan autentikasi
proxy_pass http://localhost:3000/api/webhook;
}
}
Logika Satisfy: Menggabungkan Autentikasi dengan Pembatasan IP #
Salah satu fitur Nginx yang paling kuat adalah direktif satisfy. Direktif ini menentukan bagaimana Nginx memperlakukan kombinasi antara dua modul keamanan: HTTP Basic Auth dan Access Control List (ACL) berbasis IP (direktif allow dan deny).
Ada dua nilai untuk direktif satisfy:
satisfy all(Default): Klien harus memenuhi kedua kondisi. Klien wajib terhubung dari alamat IP yang diizinkan dan wajib memasukkan username & password yang benar.satisfy any: Klien cukup memenuhi salah satu kondisi saja. Klien yang datang dari IP tepercaya langsung diizinkan masuk tanpa popup password, sedangkan klien dari IP lain tetap bisa masuk asalkan memiliki password yang benar.
Contoh Implementasi satisfy any untuk Lingkungan Kerja Kolaboratif
#
Skenario ini sangat populer digunakan pada server staging perusahaan. Kita ingin tim internal developer yang terhubung melalui jaringan kabel kantor atau koneksi VPN internal dapat langsung mengakses situs staging secara instan tanpa perlu repot mengetik username/password berulang kali. Sementara itu, jika mereka bekerja dari luar kantor (IP rumah atau Wi-Fi publik), mereka tetap dapat masuk dengan memasukkan kredensial sandi.
location /staging/ {
# Terapkan logika satisfy ANY (cukup salah satu terpenuhi)
satisfy any;
# Kondisi 1: Daftar IP tepercaya (internal kantor & VPN)
allow 10.0.0.0/8; # Subnet VPN Internal
allow 192.168.1.0/24; # Jaringan Wi-Fi Kantor
allow 203.0.113.50; # IP Publik Statis Kantor
deny all; # IP lain wajib memvalidasi kondisi berikutnya
# Kondisi 2: Kredensial Basic Auth
auth_basic "Akses Staging Luar Jaringan";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://staging_backend;
}
Dengan konfigurasi di atas:
- Request dari IP
203.0.113.50cocok dengan aturanallow 203.0.113.50. Karenasatisfy anyaktif, Nginx langsung meneruskan request ke backend tanpa memunculkan kotak login. - Request dari IP umum rumah (misalnya
182.1.2.3) akan melewati pengecekan IP dan menabrak aturandeny all(Kondisi 1 gagal). Namun, Nginx tidak langsung memblokirnya dengan status 403 Forbidden. Nginx beralih memeriksa Kondisi 2 dan memunculkan kotak login. Jika pengguna memasukkan password dengan benar, akses tetap diberikan.
Keterbatasan HTTP Basic Authentication #
Meskipun HTTP Basic Auth sangat mudah digunakan, kita harus memahami beberapa keterbatasan mendasar sebelum mengandalkannya untuk arsitektur sistem berskala besar:
- Tidak Ada Fitur Logout Bersih: Protokol HTTP Basic Auth bersifat stateless. Sekali pengguna memasukkan password yang benar, browser akan menyimpan kredensial tersebut di memori lokalnya dan mengirimkan header
Authorizationsecara otomatis pada setiap request berikutnya ke domain tersebut. Tidak ada tombol “Logout” yang disediakan oleh browser. Untuk menghapus sesi login, pengguna terpaksa harus menutup seluruh jendela browser mereka atau menghapus riwayat penjelajahan (cache) browser. - Masalah Manajemen Pengguna: Berkas
.htpasswdadalah file teks statis lokal di server. Jika kita memiliki ratusan pengguna atau membutuhkan integrasi sistem login terpusat (seperti LDAP, Active Directory, Google Workspace SSO, atau Okta), mengelola file.htpasswdsecara manual di setiap server Nginx menjadi tidak efisien. - Tidak Ada Otorisasi Granular: Semua user yang terdaftar di berkas
.htpasswdmemiliki tingkat akses yang sama (semua atau tidak sama sekali). Kita tidak bisa membedakan peran (Role-Based Access Control), misalnya user A hanya boleh membaca sedangkan user B boleh mengedit. - Rentan Brute-Force: Kotak login browser tidak memiliki proteksi bawaan terhadap percobaan masuk berulang kali secara otomatis (brute-force). Tanpa adanya tambahan konfigurasi Rate Limiting (seperti modul
limit_reqyang kita bahas di artikel berikutnya), peretas dapat dengan mudah mencoba ribuan kombinasi password per detik.
Solusi Alternatif Tingkat Lanjut #
Jika aplikasi kita tumbuh besar dan keterbatasan di atas mulai menjadi masalah, kita disarankan bermigrasi ke solusi berikut:
- OAuth2 Proxy: Modul pihak ketiga yang diletakkan di depan Nginx untuk memverifikasi token login dari penyedia identitas eksternal (Google, GitHub, Keycloak, Okta) sebelum request diizinkan masuk ke Nginx.
- Nginx Auth Request Module (
ngx_http_auth_request_module): Mengizinkan Nginx mengirim subrequest internal ke server autentikasi kustom kita untuk memverifikasi apakah request boleh masuk atau tidak sebelum diteruskan ke tujuan utama.
Ringkasan #
- Wajib Menggunakan HTTPS: Sandi Basic Auth ditransmisikan hanya dengan pengodean Base64 tanpa enkripsi. Selalu terapkan Basic Auth di atas koneksi HTTPS agar data tidak disadap.
- Gunakan Enkripsi Bcrypt: Saat membuat berkas kredensial menggunakan perintah
htpasswd, selalu sertakan parameter-Buntuk mengamankan penyimpanan sandi dengan algoritma Bcrypt.- Gunakan
auth_basic off: Kita dapat mematikan aturan login bawaan pada sub-direktori tertentu (seperti folder gambar atau endpoint webhook API eksternal) dengan direktifauth_basic off;.- Logika
satisfy any: Gabungkan kontrol IP dengan Basic Auth agar tim internal dapat masuk bebas tanpa sandi, sementara pengguna luar tetap ditantang memasukkan sandi.- Basic Auth untuk Proteksi Sederhana: Ingat bahwa Basic Auth tidak memiliki fitur logout bersih dan otorisasi terperinci. Gunakan ini hanya untuk kebutuhan proteksi halaman administratif sederhana, bukan untuk manajemen user utama aplikasi kita.