API yang kita bangun pada Section REST API menerima permintaan dari siapa pun yang mengetahui alamat servernya. Endpoint DELETE /tugas/1 akan menghapus data hanya bermodal URL — padahal tugas itu milik seseorang tertentu. Sebelum menambahkan mekanisme keamanan, kita perlu memisahkan dua pertanyaan yang sering dicampuradukkan: siapa pengirim permintaan, dan apa yang boleh dilakukan pengirim itu. Chapter ini membahas kerangka berpikirnya; chapter-chapter berikutnya mewujudkannya dalam kode Node.js mulai dari penyimpanan sandi hingga kontrol akses berbasis peran.
Authentication Menjawab Siapa #
Authentication adalah proses memverifikasi identitas pengirim permintaan. Ketika Budi mengirim email dan sandi ke endpoint login, server memeriksa apakah pasangan itu cocok dengan rekaman yang dimiliki; bila cocok, server tahu permintaan selanjutnya dari Budi memang datang dari Budi. Authorization baru berjalan setelah identitas diketahui: server menentukan apakah Budi boleh menghapus tugas nomor 1 — misalnya karena tugas itu milik Budi, atau karena peran Budi adalah admin.
Urutan ini penting. Authorization tanpa authentication tidak bermakna — “boleh menghapus” selalu terikat pada identitas tertentu, bukan pada permintaan anonim. Sebaliknya, authentication tanpa authorization hanya memberi tahu siapa pengirimnya tanpa membatasi apa pun yang bisa dilakukan.
| Aspek | Authentication | Authorization |
|---|---|---|
| Pertanyaan yang dijawab | Siapa pengirim permintaan ini? | Apa yang boleh dilakukan pengguna itu? |
| Urutan berjalan | Selalu lebih dulu | Setelah identitas diketahui |
| Status saat gagal | 401 (belum atau gagal masuk) | 403 (identitas diketahui, izin kurang) |
| Contoh mekanisme | sandi + hash, session, token | daftar izin, peran, kepemilikan data |
Tiga Kelompok Faktor Autentikasi #
Cara membuktikan identitas (faktor) terbagi tiga kelompok besar. Menggabungkan dua faktor dari kelompok berbeda menghasilkan multi-factor authentication (MFA) — inilah alasan kebocoran satu faktor belum tentu membuat akun bisa dimasuki pihak lain.
| Kelompok | Dasar pembuktian | Contoh |
|---|---|---|
| Knowledge (pengetahuan) | Sesuatu yang hanya diketahui pemiliknya | sandi, PIN, jawaban pertanyaan pemulihan |
| Possession (kepemilikan) | Sesuatu yang hanya dimiliki pemiliknya | ponsel untuk kode OTP, kunci keamanan fisik, file kunci |
| Inherent (melekat) | Karakteristik tubuh pemiliknya | sidik jari, wajah, pola retina |
Aplikasi web Node.js paling sering memakai faktor knowledge (sandi) sebagai pintu masuk pertama, lalu menambahkan faktor possession lewat kode OTP atau kunci keamanan untuk akun yang lebih sensitif.
Di Mana Status Login Disimpan #
HTTP bersifat tanpa status: setiap permintaan berdiri sendiri dan server tidak mengingat permintaan sebelumnya. Agar Budi tidak perlu mengirim sandi pada setiap permintaan, hasil login harus diwakili sesuatu yang menyertai permintaan berikutnya. Ada dua keluarga solusi, dan seluruh chapter pada Section ini berdiri di atas pilihan di antara keduanya.
| Aspek | Session (stateful) | Token seperti JWT (stateless) |
|---|---|---|
| Lokasi data login | Di server (Map, database, Redis) | Tertera di dalam token yang disimpan klien |
| Yang dikirim klien | Cookie berisi id sesi | Token pada header Authorization |
| Cara server memverifikasi | Mencari id sesi di penyimpanan | Menghitung ulang tanda tangan token |
| Mencabut akses segera | Mudah: hapus sesi dari penyimpanan | Sulit: token tetap valid sampai kedaluwarsa |
| Beban saat membesar | Penyimpanan harus dibagi antar server | Server tidak butuh penyimpanan bersama |
Tidak ada pemenang mutlak. Aplikasi monolit biasanya nyaman dengan session; API publik yang dilayani banyak server lebih sering memilih token. Kita akan membangun keduanya dari nol agar keputusan kelak diambil berdasarkan pengalaman, bukan tren.
Alur Lengkap dalam Satu Diagram #
Bagan berikut merangkai kedua gerbang tersebut dalam satu alur permintaan yang khas:
Titik kritisnya ada dua: pertukaran kredensial dengan bukti login di awal, lalu pemeriksaan bukti itu pada setiap permintaan berikutnya. Format bukti inilah yang membedakan session (Chapter Session dan Cookie) dari token (Chapter Token dan JWT).
Kedua Gerbang dalam Bentuk Kode #
Sebelum menyentuh HTTP, mari kita lihat kedua pertanyaan itu bekerja dalam satu berkas sederhana. Program berikut memisahkan data profil dari data kredensial, lalu menyediakan dua function sesuai dua gerbang kita.
// Basis data contoh: profil pengguna dan kredensial dipisah.
const profil = new Map([
['[email protected]', { nama: 'Budi', peran: 'editor' }],
['[email protected]', { nama: 'Siti', peran: 'admin' }],
]);
const kredensial = new Map([
['[email protected]', 'sandi-budi-2026'],
['[email protected]', 'sandi-siti-2026'],
]);
// Pertanyaan pertama - authentication: siapa pengirim permintaan ini?
function autentikasi(email, sandi) {
const sandiTersimpan = kredensial.get(email);
if (sandiTersimpan === undefined || sandiTersimpan !== sandi) return null;
return profil.get(email);
}
// Pertanyaan kedua - authorization: apa yang boleh dilakukan pengguna itu?
function boleh(user, aksi) {
const izin = {
baca: ['editor', 'admin'],
tulis: ['editor', 'admin'],
hapus: ['admin'],
};
return izin[aksi].includes(user.peran);
}
const budi = autentikasi('[email protected]', 'sandi-budi-2026');
console.log('Login Budi :', budi.nama, `(${budi.peran})`);
console.log('Login sandi salah :', autentikasi('[email protected]', 'sandi-salah'));
console.log('Budi baca tugas :', boleh(budi, 'baca'));
console.log('Budi hapus tugas :', boleh(budi, 'hapus'));
const siti = autentikasi('[email protected]', 'sandi-siti-2026');
console.log('Siti hapus tugas :', boleh(siti, 'hapus'));Output yang Dihasilkan:
Login Budi : Budi (editor)
Login sandi salah : null
Budi baca tugas : true
Budi hapus tugas : false
Siti hapus tugas : trueMari kita telaah bagian-bagian pentingnya:
- Baris 2-9 (dua
Mapterpisah): profil dan kredensial disimpan terpisah sejak awal — kebiasaan yang memudahkan saat kredensial nantinya dipindah ke tabel khusus dengan hash. - Baris 12-16 (
function autentikasi): menerima email dan sandi, mengembalikannullbila sandi tidak cocok, atau object profil bila cocok. Nilai baliknullinilah bentuk paling sederhana dari kegagalan authentication. - Baris 19-26 (
function boleh): menerima pengguna yang sudah terautentikasi dan nama aksi, lalu memeriksa daftar izin. Perhatikan bahwa function ini tidak pernah melihat sandi — identitas sudah jadi masukan. - Baris 28-34: Budi berhasil masuk namun ditolak untuk aksi
hapus, sementara Siti lolos karena perannyaadmin. Dua pengguna, dua hasil authorization berbeda, meski keduanya lulus authentication.
Kerangka dua gerbang ini akan menemani seluruh Section. Langkah pertama mewujudkannya menanti di depan: sandi pengguna tidak boleh disimpan dalam bentuk aslinya, sehingga Chapter Password Hashing dengan scrypt mulai dari alasan mengapa hash bukan enkripsi.
Referensi lanjutan: ringkasan HTTP authentication pada MDN memetakan istilah realm dan skema seperti Basic serta Bearer yang akan kita pakai pada chapter-chapter berikutnya.