Episode ini merangkum best practices keamanan autentikasi dari OWASP: verifikasi hanya di sisi server, timing-safe comparison, larangan mencatat secret dan kode ke log, serta alasan memakai library teruji seperti otplib alih-alih menulis TOTP dari nol.

Semua komponen 2FA sudah dipasang: enrollment, verifikasi, recovery, rate limit, dan transport. Episode 14 adalah lapisan terakhir yang menyatukan semuanya — best practices keamanan dari OWASP Authentication Cheat Sheet yang mengatur cara kerja fitur ini secara keseluruhan.
Tiga aturan yang dibahas di sini sering menjadi pembeda antara fitur 2FA yang aman dan yang sekedar terlihat aman: verifikasi di sisi server, perbandingan yang tahan timing attack, dan disiplin logging. Ditambah satu anti-pattern klasik: menulis TOTP sendiri dari nol.
Setiap kode TOTP harus diverifikasi di server, tidak pernah di JavaScript browser. Validasi di client hanya untuk kenyamanan pengguna — misalnya memastikan input 6 digit — tapi keputusan benar-salah mutlak di server. Klien bisa dimodifikasi, dan data yang dikirim bisa dipalsukan.
Praktik ini juga berarti endpoint verifikasi harus menolak input yang tidak masuk akal sebelum menghitung: panjang bukan 6 digit, bukan angka, atau field yang hilang. Semakin sedikit kerja yang dilakukan server pada input tak valid, semakin kecil permukaan untuk serangan.
Pesan error yang membedakan "password salah" dan "kode salah" membantu penyerang memetakan akun. Satu respons generik untuk kegagalan kredensial — tanpa menyebut bagian mana yang gagal — menyulitkan pengumpulan informasi. Episode 6 menerapkan prinsip ini pada pesan verifikasi kode.
Perbandingan string biasa mengembalikan false begitu menemukan karakter yang berbeda. Penyerang yang bisa mengukur waktu respons bisa menebak kode karakter demi karakter — serangan yang disebut timing attack. Kode 6 digit menjadi jauh lebih lemah jika karakter dapat ditebak satu per satu.
Kabar baiknya: library seperti otplib menangani perbandingan ini secara internal dengan operasi yang waktunya konstan. Kalian tidak perlu menulis perbandingan sendiri — cukup pastikan tidak mengganti authenticator.check dengan perbandingan manual:
const aman = authenticator.check(req.body.token, secret);
const rapuh = req.body.token === expectedCode;Baris aman dihitung dengan perbandingan timing-safe oleh otplib, sedangkan baris rapuh membocorkan informasi melalui waktu. Aturan emasnya: biarkan library yang menangani perbandingan kriptografi.
Timing attack pada aplikasi web nyata lebih sulit dieksekusi karena latensi jaringan menutupi perbedaan kecil, tapi jangan pernah memberi kesempatan. Prinsip pertahanan yang sama berlaku untuk pesan error dan jalur kode: semua hasil harus diproses dengan jalur yang nyaris identik.
Baris log yang berisi secret Base32, kode TOTP, atau URI provisioning adalah kecelakaan yang menunggu terjadi. Debugger sementara di endpoint verifikasi sering meninggalkan jejak seperti ini. Audit semua jalur log dan pastikan hanya peristiwa yang dicatat:
mfa_enabled user=550e8400-e29b-41d4-a716-446655440000
mfa_disabled user=550e8400-e29b-41d4-a716-446655440000
mfa_failed user=550e8400-e29b-41d4-a716-446655440000 attempts=3Catat identitas pengguna dan hasilnya, bukan inputnya. Jika perlu menyimpan jejak untuk forensik, simpan hash satu arah dari kode yang gagal — bukan plaintext.
Middleware yang mencatat seluruh body request secara otomatis akan menangkap password dan kode TOTP. Konfigurasikan logging untuk mengecualikan body pada route auth dan MFA, atau gunakan library logging yang sadar field sensitif.
TOTP tampak sederhana — HMAC, truncation, modulo — tapi detailnya penuh jebakan: endianness counter, encoding Base32, padding, dan perilaku window. Implementasi sendiri yang tampak benar bisa menghasilkan kode yang kadang diterima, kadang tidak, atau tidak kompatibel dengan Google Authenticator.
Gunakan library yang mengikuti RFC dan telah diuji terhadap test vector:
npm install otplib@13.4.1
pip install pyotp==2.10.0otplib@13.4.1 untuk Node.js dan pyotp untuk Python keduanya mengikuti RFC 4226 dan RFC 6238, diuji terhadap test vector resmi, dan kompatibel dengan Google Authenticator. Menulis ulang dari nol hanya dibenarkan untuk kepentingan belajar — episode 16 bahkan memakai library untuk menguji implementasi.
Selain keamanan, library memberi satu keuntungan yang sulit ditiru implementasi manual: kompatibilitas. otplib dan pyotp diuji terhadap Google Authenticator, Microsoft Authenticator, dan Authy di banyak versi, sehingga secret yang dibuat di satu ekosistem tetap valid di ekosistem lain. Implementasi sendiri sering lolos uji internal tapi gagal ketika dipakai lintas aplikasi.
Rangkuman praktik yang dibahas di episode 7 sampai 14 dalam satu daftar yang bisa kalian tempel di dinding:
Daftar ini adalah persimpangan dari semua episode sebelumnya. Kalau satu item terlewat, asumsikan fitur 2FA kalian belum siap produksi.
Episode 14 menyatukan best practices OWASP: verifikasi murni di sisi server, perbandingan timing-safe yang ditangani library, disiplin logging tanpa secret dan kode, serta keputusan memakai library teruji alih-alih menulis TOTP dari nol.
Inti yang harus dibawa pulang:
Di episode 15 selanjutnya kita akan membahas session, token, dan trusted devices — session jangka pendek dengan rotasi id, logout menyeluruh, cookie trusted device yang terpisah, serta hubungan JWT dengan flag 2FA saat token dikeluarkan.