Passkey untuk Aplikasi Web Kecil — Apa yang Berubah di Server, dan Apa yang Tidak
Ada momen tertentu dalam kehidupan sebuah aplikasi web kecil ketika formulir login mulai terasa sebagai beban, bukan fitur. Password bocor, orang memakai ulang password yang sama, dan menambahkan second factor berarti meminta setiap pengguna untuk membaca kode berputar yang pendek dari ponsel yang mungkin ada di ruangan lain. Passkey biasanya ditawarkan tepat pada momen itu sebagai jalan keluar, dan pemasaran di sekitarnya cukup percaya diri sehingga orang mudah mengira masalahnya saja hilang.
Masalahnya tidak hilang, dan perubahannya juga tidak semuanya bergerak ke satu arah. Pertanyaan awal aku untuk tulisan ini lebih sempit dan lebih praktis: kalau sebuah aplikasi kecil berpindah dari password plus aplikasi autentikator ke passkey, apa sebenarnya yang berubah di sisi server, dan apa yang tetap membandel?
Aku ingin menjelaskan dasar bukti tulisan ini sebelum lanjut. Semua klaim faktual di sini berasal dari dua dokumen yang aku baca per bagian untuk topik yang dibahas di bawah, yaitu spesifikasi Web Authentication Level 3 dan NIST SP 800-63B-4, ditambah dokumentasi rujukan dari MDN dan OWASP. Ini bukan laporan sebuah implementasi. Aku tidak memasang passkey di situs ini, dan aku tidak punya data tentang berapa banyak akun yang benar-benar akan mendaftar. Di mana spesifikasi bersifat preskriptif, aku sebutkan apa yang diwajibkan; di mana dia meninggalkan keputusan kepada implementer, aku coba menandainya sebagai pertanyaan terbuka, bukan menyodorkannya sebagai best practice.
Apa itu passkey, secukupnya agar berguna
Kata "passkey" tidak menunjuk mekanisme yang terpisah: glosarium spesifikasi mencantumkannya sebagai nama lain untuk discoverable credential. Saat kamu mendaftarkan satu, sebuah authenticator membuat sepasang kunci. Separuh privatnya tetap ada di authenticator, dan untuk passkey yang tersinkronisasi antarperangkat, itu berarti isinya bisa disalin ke penyimpanan sebuah penyedia, komplikasi yang akan aku bahas lagi nanti. Separuh publiknya dikirim ke server dan dikaitkan dengan akunmu. Saat kamu masuk lagi, authenticator menandatangani challenge yang dikirim server memakai kunci privat, lalu server memeriksa tanda tangan itu terhadap kunci publik yang sudah dimilikinya. Yang melintasi jaringan adalah kunci publik dan tanda tangan yang terikat pada challenge yang baru, bukan secret yang bisa dipakai berulang kali.
Dengan one-time password berbasis waktu, susunannya berbeda. NIST menggambarkan sistem OTP single-factor sebagai sesuatu yang memuat dua nilai persisten: kunci simetris yang bertahan selama hidup authenticator, dan nonce yang berubah setiap kali dipakai atau diturunkan dari jam nyata. Kode yang diharapkan dihitung dari kunci dan nonce itu, sehingga verifier membutuhkan kunci tersebut secara langsung dan tidak bisa menyimpan hanya hash-nya. Kamu bisa membatasi laju kode itu, mengenkripsi secret ketika tersimpan, dan membatasi siapa yang boleh membacanya, dan tidak satu pun itu mengubah fakta bahwa server memegang material yang bisa menghasilkan kode yang sah. Passkey menghapus kelas masalah itu untuk credential-nya sendiri.
Panduan NIST menarik garis yang lebih tajam antara keduanya, dan alasannya berkaitan dengan phishing. Dokumen itu menyatakan bahwa authenticator yang melibatkan input manual atas output authenticator, dengan menyebut authenticator out-of-band dan OTP sebagai contoh, shall not dianggap phishing-resistant, karena input manual itu tidak mengikat output tersebut ke sesi spesifik yang sedang diautentikasi. WebAuthn disebut dalam dokumen yang sama sebagai standar yang menyediakan phishing resistance lewat verifier name binding, dengan memilih authenticator secret berdasarkan nama domain terverifikasi milik verifier. Itu adalah klaim tentang struktur protokolnya, bukan tentang tingkat kewaspadaan penggunamu.
Tiga peran penting untuk sisa artikel ini, dan spesifikasi memakainya secara presisi. Relying party adalah situs yang ingin memverifikasi kamu, yang berarti servermu. User agent adalah browser, dan dia menyediakan API supaya sebuah halaman bisa bicara dengan perangkat keras yang tidak dikendalikannya. Authenticator adalah pihak yang benar-benar memegang kunci privat: sesuatu yang dibangun di dalam user agent atau sistem operasi, seperti Windows Hello, atau token fisik seperti security key USB atau Bluetooth. Glossary spesifikasi menambahkan satu istilah yang khususnya penting untuk passkey: client platform adalah client device bersama dengan client-nya, dan perangkat keras yang sama bisa menjadi bagian dari beberapa client platform yang berbeda seiring waktu ketika perangkat itu menjalankan sistem operasi yang berbeda.
Di web, passkey adalah WebAuthn, dan MDN menandai API ini sebagai tersedia lintas browser sejak September 2021 serta mencatat bahwa API ini hanya jalan di secure context, artinya HTTPS. Aku akan membaca kombinasi itu sebagai prasyarat untuk adopsi sama sekali: API browser yang hanya jalan di balik sertifikat yang tidak dimiliki pengunjung rata-rata akan menyurung passkey ke dalam proyek sampingan.
Dua ceremony adalah pekerjaan sebenarnya
Registrasi dan autentikasi biasanya digambarkan sebagai satu alur, dan itu menyembunyikan bagian yang menentukan apakah sebuah implementasi benar. Keduanya adalah dua ceremony terpisah, dan server punya daftar pemeriksaan untuk masing-masing. Level 3 spesifikasi menyebut daftar-daftar ini secara eksplisit, dan aplikasi kecil yang mampu menerapkannya, tetapi hanya jika memperlakukannya sebagai daftar periksa, bukan sebagai panggilan library dengan aura keamanan.
Registrasi dimulai dengan server membuat sebuah challenge, mengirimkannya ke browser, lalu browser meminta authenticator membuat credential. Authenticator mengembalikan kunci publik yang baru dibuat, sebuah identifier untuk credential itu, dan sebuah attestation statement. Server kemudian memverifikasi, antara lain, bahwa hash dari relying party identifier di dalam authenticator data cocok dengan identifier yang diharapkan, bahwa bit user-presence aktif kecuali permintaannya datang dari autofill kondisional, bahwa bit user-verification aktif jika server meminta user verification, bahwa bit backup-state konsisten secara internal, bahwa algoritmanya cocok dengan salah satu yang ditawarkan server, dan bahwa credential identifier itu belum terdaftar pada pengguna lain. Level 3 membatasi credential identifier maksimal 1023 byte dan menyatakan bahwa yang lebih besar sebaiknya menggagalkan ceremony ini.
Pemeriksaan terakhir itu bukan sekadar pedantik. Spesifikasi menjelaskan alasannya: penyerang yang berhasil memperoleh credential identifier dan credential public key milik seorang pengguna untuk sebuah situs bisa mencoba mendaftarkan credential korban sebagai miliknya sendiri, dan menolak identifier yang sudah dikenal itulah yang menghentikan penggantian tersebut.
Autentikasi terlihat lebih sederhana dari luar, dan di situlah aku akan mengharapkan implementasi buatan tangan gagal. Server menerbitkan challenge yang baru, browser mengembalikan assertion yang sudah ditandatangani, dan server memeriksa daftar yang menurutku layak ditulis ulang dengan bahasa biasa karena urutan langkahnya penting:
- tipe di dalam client data adalah
webauthn.get; - challenge-nya sama dengan yang baru diterbitkan server, dalam encode base64url;
- origin-nya salah satu yang diharapkan server;
- hash dari relying party identifier cocok dengan identifier yang diharapkan server;
- bit user-presence aktif, dan bit user-verification jika verifikasi diwajibkan;
- tanda tangannya terverifikasi atas konkatenasi authenticator data dengan hash dari client data.
Setiap pemeriksaan itu punya pekerjaan spesifik. Pemeriksaan challenge menghentikan replay. Pemeriksaan origin itulah yang mengikat assertion ke situsmu. Pemeriksaan relying party identifier itulah yang menghentikan credential yang terdaftar di situs lain supaya tidak terpakai di sini.
Challenge layak dilihat sekali lagi, karena spesifikasi justru blak-blakan tentang hal ini. Sebuah bagian khusus menyatakan bahwa challenge untuk pembuatan dan challenge untuk permintaan keduanya harus dibangkitkan secara acak oleh relying party di lingkungan yang dipercayainya, seperti server, dan bahwa nilai yang dikembalikan harus cocok dengan yang dibangkitkan. Bagian yang sama mengatakan bahwa relying party sebaiknya menyimpan challenge itu sementara sampai operasi selesai, sebaiknya hanya membuatnya valid untuk rentang waktu yang mirip dengan batas atas ceremony timeout, dan sebaiknya membuatnya minimal 16 byte. Dalam praktiknya, artinya challenge adalah nilai yang terikat pada sesi, berumur pendek, dan sekali pakai. Memperlakukannya lebih rendah dari itu akan diam-diam menghapus perlindungan replay yang justru ada supaya seluruh daftar itu bekerja.
Ada satu detail lagi yang mudah terlewat. Level 3 mengatakan user verification sebaiknya diwajibkan jika, dan hanya jika, request mengaturnya menjadi required. Kalau servermu tidak memintanya, spesifikasi menyuruhmu mengabaikan bit user-verification, bukan memperlakukannya sebagai faktor tambahan yang kebetulan kamu terima.
Discoverable credential dan prompt autofill
Ada dua cara server mengarahkan authenticator ke sebuah credential tertentu. Dengan non-discoverable credential, server memberikan identifier credential yang sudah disimpannya, dan itulah sebabnya pengguna biasanya harus mengetik username lebih dulu. Dengan discoverable credential, server tidak memberikan apa pun, dan authenticator bisa menawarkan setiap credential yang dimilikinya untuk relying party tersebut. Level 3 menamai ulang area ini, dan sejarah penamaannya adalah pengingat kecil bahwa bidang ini masih muda: istilah "discoverable credential" adalah istilah spesifikasi, sementara "resident key" masih bertahan di API dan di data model demi backwards compatibility.
MDN mencatat satu akibat yang punya bobot praktis bagi setiap situs yang sudah punya login password: menurut definisinya, passkey selalu harus berupa discoverable credential. Itulah yang membuat pengalaman autofill mungkin terjadi, yaitu browser mengundang pengguna untuk masuk dengan passkey hanya jika ada passkey yang cocok tersedia saat itu, alih-alih meminta pengguna memilih di antara dua mekanisme. Perubahan markup-nya cuma satu token tambahan di dalam atribut autocomplete, yaitu webauthn, yang dijelaskan baik oleh dokumentasi browser maupun oleh spesifikasinya. Untuk situs yang sudah berbasis password, itu mungkin bedanya antara opsi passkey yang benar-benar dipakai dan opsi passkey yang dilewati orang.
Flag adalah bagian yang jujur dari cerita ini
Authenticator data WebAuthn membawa sekumpulan kecil flag, dan di situlah trade-off yang menarik muncul. Empat di antaranya layak diketahui namanya: user present, user verified, backup eligible, dan backup state.
Dua yang pertama sudah akrab. Pasangan kedua lebih baru dalam praktik dan jauh lebih jarang dibahas. Level 3 mendefinisikan kombinasi-kombinasinya, dan tabelnya cukup pendek untuk dikutip:
| Backup eligible | Backup state | Makna |
|---|---|---|
| 0 | 0 | Credential satu perangkat. |
| 0 | 1 | Tidak diizinkan. |
| 1 | 0 | Credential multi-perangkat, belum di-backup. |
| 1 | 1 | Credential multi-perangkat, saat ini sudah di-backup. |
Sumber: WebAuthn Level 3, credential backup state.
Makna sebenarnya lebih penting daripada yang disyaratkan tabel. Credential yang bisa disinkronkan, yang bisa disalin ke tempat lain, dan yang benar-benar sudah disalin adalah tiga hal berbeda, dan hanya yang terakhir yang dilaporkan oleh flag backup state. Backup eligible disetel saat pembuatan credential dan tidak boleh berubah setelahnya, sedangkan backup state berubah seiring waktu. Spesifikasi merekomendasikan agar relying party menyimpan nilai-nilai terbaru, lalu menyarankan perilaku yang tidak sesederhana kelihatannya pertama kali.
Kalau sebuah credential tidak backup eligible, itu credential satu perangkat yang authenticator pembuatnya tidak akan pernah izinkan untuk di-backup, dan spesifikasi mengatakan relying party sebaiknya memastikan setiap akun punya authenticator tambahan atau proses pemulihan. Kalau backup state bergerak dari nol ke satu, credential itu sudah terlindungi dari kehilangan satu perangkat, dan server boleh meminta pengguna meningkatkan keamanan akunnya lalu menghapus password-nya. Kalau bergerak dari satu kembali ke nol, karena layanan backup dimatikan atau sekadar gagal, relying party sebaiknya memandu pengguna untuk memvalidasi faktor autentikasi lain yang ia miliki, dan kalau ia tidak punya satu pun, untuk menambahkan.
Baca kasus terakhir itu apa adanya: sebuah penerapan passkey adalah state machine akun yang sekarang harus memperhatikan satu bit yang berbalik, lalu membantu orang menyelesaikan akibatnya. Untuk blog satu orang, itu fitur yang boleh dilewati. Untuk aplikasi dengan akun sungguhan, itu tugas desain, bukan sekadar polesan akhir.
Panduan NIST tentang flag yang sama lebih hati-hati, dan menurutku itulah teks yang lebih berguna untuk situs yang menghadap publik. Di lampiran soal syncable authenticator, SP 800-63B-4 mengatakan bahwa verifier boleh memakai flag backup eligible untuk membatasi syncable authenticator, tetapi bahwa agencies sebaiknya tidak bersyarat penerimaan pada flag backup state untuk aplikasi yang menghadap publik karena alasan pengalaman pengguna. Dokumen itu juga memperingatkan bahwa ketidaktersediaan attestation sebaiknya tidak menghalangi pemakaian syncable authenticator, karena attestation terbatas pada produk konsumen dan mewajibkannya cenderung mengalihkan pengguna ke opsi yang lebih tidak aman.
Itu koreksi yang berguna untuk kegembiraan berlebihan terhadap flag-flag itu. Flag itu informatif, bukan policy engine, dan aplikasi kecil yang mulai menolak credential tersinkronisasi berdasarkan backup state sebagian besar hanya akan menghasilkan pertanyaan dari pengguna.
Signature counter adalah sinyal, bukan bukti
Authenticator data juga membawa signature counter, yaitu signCount, dan spesifikasi terasa sangat jujur tentang batasannya. Authenticator sebaiknya mengimplementasikannya, tetapi yang tidak melakukannya membiarkan nilainya tetap nol, sehingga relying party harus menangani nol di kedua sisi. Bahkan ketika kedua nilai bukan nol, nilai baru yang lebih kecil atau sama dengan nilai tersimpan hanya menunjukkan bahwa ada sesuatu yang mungkin salah: dua salinan atau lebih dari credential private key mungkin ada dan dipakai bersamaan, authenticator mungkin mengalami gangguan, atau relying party itu sendiri mungkin memproses assertion di luar urutan. Spesifikasi secara eksplisit menyebut ini sinyal, bukan bukti, dan menyerahkan keputusan apakah ceremony ini harus digagalkan kepada implementer.
Bagian yang sama meminta authenticator mengimplementasikan counter per credential, bukan satu counter global, dengan alasan bahwa counter yang dipakai bersama bisa dipakai sebagai correlation handle untuk pengguna lintas situs. Layak diperhatikan apa yang diasumsikan oleh pembahasan itu. Bagian security considerations pada spesifikasi menyatakan bahwa dia tidak mendefinisikan protokol apa pun untuk membackup credential private key atau untuk membagikannya di antara authenticator, dan bahwa secara umum diharapkan credential private key tidak pernah meninggalkan authenticator yang membuatnya. Untuk credential yang seluruh tujuan memang adalah disalin antarperangkat, deteksi clone berbasis counter adalah salah satu alasan paling lemah untuk merasa tenang, dan aku tidak menemukan requirement di spesifikasi bahwa credential semacam itu harus melaporkan counter yang bermakna.
Yang tidak berubah: pemulihan akun
Inilah bagian yang akan kurotekan di urutan teratas setiap keputusan passkey, dan juga bagian yang paling sering dilewatkan dari perbandingan. Menghapus shared secret dari loginmu tidak menghapus kebutuhan untuk mengembalikan orang yang kehilangan akses ke akunnya.
NIST memperlakukan pemulihan akun sebagai peristiwa yang terpisah dari autentikasi, dengan empat kelas metode yang diakui: saved recovery code, issued recovery code, recovery contact, dan identity proofing berulang. Dalam rumusan NIST, sebuah credential service provider shall mendukung minimal salah satunya. Untuk saved recovery code, kodenya harus memuat minimal 64 bit dari approved random bit generator, disimpan di akun dalam bentuk hashed, dan dimaksudkan untuk disimpan subscriber secara offline. Setiap peristiwa pemulihan akun selalu menyebabkan setidaknya satu notifikasi, dan justru supaya pemulihan yang curang itu kelihatan.
Ada gunanya menjaga cakupan ini tetap terlihat di depan mata. SP 800-63B ditulis untuk federal agencies di Amerika Serikat dan tidak mengikat situs kecil; abstraknya mendeskripsikan panduan untuk subjek yang berinteraksi dengan government information systems. Itu hanya panduan publik paling eksplisit tentang pertanyaan ini yang aku temukan, dan penalarannya tidak spesifik pada pemerintah mana pun.
Dibaca berdampingan dengan cerita credential, ringkasannya yang jujur adalah ini. Passkey memperbaiki keamanan dari alat yang kamu pakai untuk verifikasi. Mereka sama sekali tidak melakukan apa-apa terhadap proses yang kamu pakai untuk membangun ulang identitas ketika alat itu hilang. Aplikasi yang mengadopsi passkey lalu membiarkan jalur reset password-nya tetap lemah seperti sebelumnya belum menyelesaikan pekerjaannya, dan mungkin malah memperburuk keadaan, karena jalur reset kini menjadi satu-satunya jalan masuk yang tersisa. Jawaban spesifikasi sendiri terhadap credential loss bukan mekanisme backup, melainkan keluasan: relying party sebaiknya mengizinkan dan mendorong pengguna untuk mendaftarkan beberapa credential pada satu akun, sehingga kehilangan satu perangkat tidak sama dengan kehilangan akun.
Ada satu "tidak berubah" kedua yang layak dinyatakan terus terang. Passkey menjawab pertanyaan autentikasi. Mereka tidak mengatakan apa pun tentang otorisasi, tentang apa yang boleh dilakukan pengguna yang sudah terautentikasi, dan tidak ada apa pun tentang session yang menyusul. Assertion passkey yang valid tapi menghasilkan session cookie berumur panjang dengan cakupan yang buruk hanya memindahkan kesalahan yang sama satu lapis ke atas, dan itulah sebabnya nasihat yang sudah ada tentang session identifier, cookie flag, dan idle timeout tidak terpengaruh oleh apa pun di dalam artikel ini.
Dua kritik yang layak diperlakukan serius
Yang pertama soal berbagi. Berbagi password itu buruk, dan berbagi passkey justru menjadi fitur yang sengaja ditawarkan sebagian implementasi. NIST menyinggung soal ini secara blak-blakan. Panduan selama ini memperingatkan agar authenticator tidak dibagikan antar pengguna. Sebagian implementasi syncable justru aktif mendorong berbagi sebagai alternatif yang lebih aman daripada berbagi password. Mitigasi yang tersedia lewat device management untuk enterprise tidak punya padanan bagi aplikasi yang menghadap publik. Agencies di posisi itu sebaiknya menganggap semua syncable authenticator bisa dipakai bersama. Apa pun yang lain dikerjakan passkey, mereka tidak membuat berbagi akun hilang, dan mereka menyerahkan sebagian kebijakan itu kepada pihak yang menyimpan salinan tersinkronisasinya.
Yang kedua soal mengasumsikan perangkat keras. Godaan untuk mengasumsikan bahwa sebuah passkey tinggal di secure element dan tidak bisa diekstrak itu nyata. Panduan autentikasi OWASP justru hati-hati di titik ini. Untuk banyak authenticator, termasuk passkey platform yang umum, kunci privatnya dibangkitkan dan disimpan oleh secure key manager milik sistem operasi. Kunci bisa dilindungi oleh komponen berbasis perangkat keras seperti TPM, Secure Enclave, atau Android Keystore. Namun sebagian authenticator mendukung sinkronisasi atau backup yang melibatkan ekspor atau penyimpanan sisi server, dan tidak semua implementasi berbasis perangkat keras. Rekomendasi eksplisitnya adalah jangan berasumsi kunci bersifat hardware-backed dan non-exportable kecuali itu sudah diverifikasi, misalnya lewat authenticator properties atau attestation.
Kedua kritik itu menunjuk pergeseran struktural yang sama. Keamanan passkey bergantung pada rantai yang sekarang mencakup perangkat, sistem operasi, client platform, dan biasanya akun cloud yang menyimpan salinan tersinkronisasinya. Rantai itu umumnya lebih kuat daripada shared secret di dalam database, tetapi bukan rantai yang sepenuhnya kamu kendalikan.
Daftar periksa keputusan untuk aplikasi kecil
Kalau kamu menjalankan situs kecil dan sedang mempertimbangkan passkey, pertanyaan yang menurutku paling penting dijawab lebih dulu sebenarnya bukan yang bersifat teknis:
- Apakah setiap akun punya lebih dari satu authenticator, atau metode pemulihan? Spesifikasi menyarankan keduanya, dan situs dengan satu administrator yang memiliki satu laptop layak berpikir serius tentang siapa yang memulihkan akses ketika laptopnya hilang.
- Apakah jalur password tetap dipertahankan? Mempertahankan keduanya itu wajar, dan peningkatan ke versi tanpa password yang digambarkan spesifikasi baru berarti selama masih ada password yang perlu dihapus. Setiap jalur tambahan adalah satu jalur lagi yang harus dikeraskan.
- Apakah kamu memverifikasi ceremony-nya sendiri atau memakai library yang dirawat? Implementasi untuk PHP ada dan dirawat, misalnya proyek web-auth/webauthn-framework, yang menyebut dirinya sebagai kumpulan library PHP beserta satu Symfony bundle untuk mengintegrasikan WebAuthn ke aplikasi web, dan dirilis di bawah lisensi MIT. Menulis sendiri penanganan COSE dan CBOR demi menghemat satu dependency adalah tukaran yang buruk untuk tim kecil.
- Bisakah kamu menjelaskan penanganan session tanpa memakai kata "passkey"? Kalau jawabannya tidak, urutan kerjanya salah.
Ada juga versi yang perlu diperhatikan. WebAuthn Level 3 menjadi W3C Recommendation pada Agustus 2026, dan sengaja mempertahankan nama lama di API serta data modelnya demi kompatibilitas, seperti yang ditunjukkan bagian discoverable credential. Library dan API platform tidak diperbarui dengan jadwal yang sama seperti spesifikasi, jadi versi yang kamu terapkan layak dicatat dalam dokumen implementasi apa pun yang kamu simpan, dan layak dibaca ulang ketika versinya berubah.
Yang masih belum kuketahui
Beberapa pertanyaan praktis masih terbuka buat aku, dan aku lebih suka menyebutkannya daripada menutupinya dengan hal lain. Seberapa baik sebuah plugin CMS atau framework mengintegrasikan ini tanpa membocorkan masalah abstraksi adalah hal yang belum aku nilai. Apakah pengalaman autofill benar-benar mengurangi tiket dukungan untuk situs kecil, atau cuma memindahkan kebingungan dari formulir login ke dalam browser, adalah pertanyaan empiris yang tidak kupunyai datanya. Dan pertanyaan yang lebih sulit di bawah keduanya: berapa banyak dari cerita keamanan ini yang masih bertahan kalau ada pengguna yang tidak pernah mengaktifkan passkey sama sekali dan tetap memakai password yang sudah dimilikinya.
Pertanyaan terakhir itulah alasan aku tidak akan menyebut ini sebagai penggantian. Untuk aplikasi kecil, passkey terlihat paling baik sebagai opsi kedua yang kuat di atas login yang sudah sehat, bukan sebagai penulisan ulang yang menghancurkan masalah-masalah yang layak diselesaikan.
Referensi
- W3C, Web Authentication: An API for accessing Public Key Credentials — Level 3, W3C Recommendation, 25 Agustus 2026. https://www.w3.org/TR/webauthn-3/
- NIST, Digital Identity Guidelines: Authentication and Authenticator Management (SP 800-63B-4), Juli 2025. https://pages.nist.gov/800-63-4/sp800-63b.html (catatan publikasi: https://csrc.nist.gov/pubs/sp/800/63/b/4/final)
- MDN Web Docs, Web Authentication API. https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API
- OWASP Cheat Sheet Series, Authentication Cheat Sheet. https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html
- GitHub, web-auth/webauthn-framework (framework FIDO-U2F / FIDO2 / WebAuthn, MIT). https://github.com/web-auth/webauthn-framework
