Panduan pengembang tentang WebAuthn & implementasi kunci sandi (passkeys). Unduh lembar contekan sebagai PDF atau gunakan situs web ini untuk semua informasi di satu tempat.
Lukas R.
Dibuat: 6 Maret 2024
Diperbarui: 3 Juli 2026

Halaman ini diterjemahkan secara otomatis. Baca versi asli berbahasa Inggris di sini.
Unduh Lembar Contekan Kunci Sandi secara gratis selengkapnya dan dapatkan semua wawasannya.
Panduan Pengembang Kunci Sandi Utama
Dapatkan referensi yang berfokus pada pengembang untuk segala hal tentang kunci sandi yang mencakup dukungan platform, perilaku browser, praktik terbaik UX, dan kiat integrasi.

Autentikasi dengan kunci sandi didasarkan pada dua proses, juga disebut seremoni,
pendaftaran (alias fase atestasi) dan login (alias fase asersi).
Setiap fase memerlukan tantangan acak yang dihasilkan oleh server, yang ditandatangani oleh
autentikator dan dikirim kembali ke server WebAuthn untuk memverifikasi
pengguna.
Eksperimen dengan alur passkey di Passkeys Debugger.
Seremoni pendaftaran menggunakan dua objek pusat: PublicKeyCredentialCreationOptions dan atestasi.
Seremoni login menggunakan dua objek pusat: PublicKeyCredentialRequestOptions dan asersi.
Lihat berapa banyak orang yang benar-benar memakai passkeys.
Untuk pendaftaran dan login dengan kunci sandi, terdapat empat objek utama:
Bagian ini juga menjelaskan objek authenticatorSelection, yang digunakan dalam PublicKeyCredentialCreationOptions.
Igor Gjorgjioski
Head of Digital Channels & Platform Enablement, VicRoads
We hit 80% mobile passkey activation across 5M+ users without replacing our IDP.
See how VicRoads scaled passkeys to 5M+ users — alongside their existing IDP.
Read the case studyPublicKeyCredentialCreationOptions adalah objek pusat dari fase atestasi (Pendaftaran). Objek ini dibuat oleh dan dikembalikan dari server WebAuthn.
{ "PublicKeyCredentialCreationOptions": { "rp": { "id": "passkeys.eu", "name": "Corbado Passkeys Demo" }, "user": { "displayName": "john.doe", "id": "dXNyLZ….DU10Tc", "name": "john@doe.com" }, "challenge": "888fix4Bus...pHHr3Y", "pubKeyCredParams": [ { "alg": -7, "type": "public-key" }, { "alg": -257, "type": "public-key" } ], "excludeCredentials": [], "authenticatorSelection": { "authenticatorAttachment": "platform", "residentKey": "required", "userVerification": "required" }, "attestation": "none", "extensions": {} } }
Objek berisi atribut ini:
Berlangganan Passkeys Substack kami untuk berita terbaru.
PublicKeyCredentialRequestOptions adalah objek pusat dari fase asersi (Login). Objek ini dibuat oleh dan dikembalikan dari server WebAuthn.
{ "publicKeyCredentialRequestOptions": { "challenge": "pT7HMA-…dFPHk", "timeout": 500, "rpId": "passkeys.eu", "userVerification": "preferred", "allowCredentials": [], "extensions": [] } }
Objek berisi atribut ini:
Selama Seremoni Atestasi / Pendaftaran, Autentikator mengembalikan Respons Pendaftaran ini. Anda dapat mencobanya sendiri di Passkeys Debugger.
{ "authenticatorAttachment": "platform", "id": "JKZbixUfKN_aZtimefYT-OjH5dw", "rawId": "JKZbixUfKN_aZtimefYT-OjH5dw", "response": { "attestationObject": { "fmt": "none", "attStmt": {}, "authData": { "rpIdHash": "PpZrl-Wqt-OFfBpyy2SraN1m7LT0GZORwGA7-6ujYkM", "flags": { "userPresent": true, "userVerified": true, "backupEligible": true, "backupStatus": true, "attestedData": true, "extensionData": false }, "counter": 0, "aaguid": { "raw": "fbfc3007-154e-4ecc-8c0b-6e020557d7bd", "name": "iCloud Keychain" }, "credentialID": "JKZbixUfKN_aZtimefYT-OjH5dw", "credentialPublicKey": "pQECAyYgASFYIPWLalDzyxIDmAADvfK8iNM5To50kh7TyPH-teEz8RMdIlgg3D7bPIWQJ8z-WFn3zdYZzJw9c7mhPdmflQqD9vV7efA", "parsedCredentialPublicKey": { "keyType": "EC2 (2)", "algorithm": "ES256 (-7)", "curve": 1, "x": "9YtqUPPLEgOYAAO98ryI0zlOjnSSHtPI8f614TPxEx0", "y": "3D7bPIWQJ8z-WFn3zdYZzJw9c7mhPdmflQqD9vV7efA" } } }, "clientDataJSON": { "type": "webauthn.create", "challenge": "k2p6f-upzP_hc6NZvmMAxiI0VSTeQIeXXVRGW62LTj0", "origin": "https://www.passkeys-debugger.io", "crossOrigin": false }, "transports": ["hybrid", "internal"], "authenticatorData": "PpZrl-Wqt-OFfBpyy2SraN1m7LT0GZORwGA7-6ujYkNdAAAAAPv8MAcVTk7MjAtuAgVX170AFCSmW4sVHyjf2mbYpnn2E_jox-XcpQECAyYgASFYIPWLalDzyxIDmAADvfK8iNM5To50kh7TyPH-teEz8RMdIlgg3D7bPIWQJ8z-WFn3zdYZzJw9c7mhPdmflQqD9vV7efA", "publicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9YtqUPPLEgOYAAO98ryI0zlOjnSSHtPI8f614TPxEx3cPts8hZAnzP5YWffN1hnMnD1zuaE92Z-VCoP29Xt58A", "publicKeyAlgorithm": -7 }, "type": "public-key", "clientExtensionResults": {} }
Atestasi berisi beberapa komponen penting seperti attestationObject, algorithm dan bendera transport.
Diambil dari Spesifikasi Webauthn W3C
attestationObject adalah objek yang dikodekan dengan CBOR, berisi informasi tentang kredensial yang baru dibuat, kunci publik, dan data relevan lainnya:
Baca selengkapnya tentang ekstensi.
Kunci sandi dihasilkan dengan algoritma COSE, menunjukkan algoritma yang digunakan dalam
atribut algoritma dari parsedCredentialPublicKey di
objek atestasi.
Berikut ikhtisar algoritma COSE yang paling relevan:
Properti transports menunjukkan mekanisme di mana autentikator dapat berkomunikasi dengan klien. Beberapa kombinasi nilai sampel umum adalah:
Selama Seremoni Asersi / Login, Autentikator mengembalikan Respons Login ini. Anda dapat mencobanya sendiri di Passkeys Debugger.
{ "id": "JKZbixUfKN_aZtimefYT-OjH5dw", "rawId": "JKZbixUfKN_aZtimefYT-OjH5dw", "type": "public-key", "authenticatorAttachment": "platform", "response": { "authenticatorData": { "rpIdHash": "PpZrl-Wqt-OFfBpyy2SraN1m7LT0GZORwGA7-6ujYkM", "flags": { "userPresent": true, "userVerified": true, "backupEligible": true, "backupStatus": true, "attestedData": false, "extensionData": false }, "counter": 0 }, "clientDataJSON": { "type": "webauthn.get", "challenge": "GCVkITWbe2l2dttsn_DgJYvH9QPHPDo0ygWgcgI6B7U", "origin": "https://www.passkeys-debugger.io", "crossOrigin": false, "other_keys_can_be_added_here": "do not compare clientDataJSON against a template. See https://goo.gl/yabPex" }, "signature": "MEQCIA-orC8N2KKWOxyY17BWP8lB-Be5to9btXRnJZf2SLhXAiBGxJe5Eu5LwOTbsyzAYmIXHOhlC3pN7s7Q1fRLvEW57g", "userHandle": "_FKz1uwqmR_3yGq6hJntzoIFwFC_d1u_53YRELh0KlE" } }
Asersi berisi beberapa komponen penting seperti bendera, tanda tangan, dan userHandle.
Berikut gambaran umum bendera paling relevan beserta kombinasinya:
Tanda tangan (signature) digunakan untuk memverifikasi bahwa pengguna yang mencoba masuk, benar-benar memiliki kunci privat. Tanda tangan dibuat dengan menggabungkan authenticatorData dan clientDataHash (yaitu versi SHA-256 dari ClientDataJSON) dan menandatangani hasil tersebut dengan kunci privat (di autentikator). Untuk memverifikasi dengan kunci publik, kami menggabungkan authenticatorData dan clientDataHash juga. Jika hasil verifikasi mengembalikan true, autentikasi berhasil.
userHandle adalah user_id yang sebenarnya. Baca selengkapnya tentang user_id di bagian 4.1 Skema Basis Data.
Objek authenticatorSelection memungkinkan server menentukan pengaturan untuk pembuatan autentikator dan kredensial dengan nilai berikut:
Kunci Residen (juga disebut Kredensial yang Dapat Ditemukan): Kunci residen disimpan di autentikator dan diambil selama autentikasi. Dengan cara ini, klien dapat menemukan daftar kunci yang mungkin, dan itulah sebabnya [Conditional UI](/id/blog/user-transition-passkeys-> conditional-ui) membutuhkan kunci residen. Kunci Non-Residen (juga disebut Kredensial yang Tidak Dapat Ditemukan): Jika berupa kunci non-residen, ID kredensial disimpan di server dan diberikan selama autentikasi. ID kredensial adalah pengenal buram dengan struktur internalnya spesifik untuk implementasi—autentikator dapat menyimpan kunci privat secara langsung, menggunakan pembungkusan kunci terenkripsi, atau mendapatkan kunci dari rahasia internal. Mekanisme yang tepat bervariasi bergantung implementasi autentikator.
Peringatan: Jika diatur ke "Preferred", pengguna atau perangkat mereka dapat melewati verifikasi pengguna dalam proses autentikasi (baca selengkapnya di artikel ini).
Conditional UI (isi otomatis kunci sandi) menampilkan kunci sandi yang tersedia dalam tarik-turun pilihan untuk pengguna, saat pengguna memiliki kunci residen yang didaftarkan pada relying party. Ini meningkatkan kegunaan kunci sandi, tetapi memerlukan upaya pengembangan tambahan dan tidak tersedia untuk semua kombinasi OS / browser.
Seperti login biasa, Conditional UI juga menggunakan objek PublicKeyCredentialRequestOptions dan asersi
Conditional UI belum tersedia di semua kombinasi sistem operasi dan browser. Berikut ringkasan cakupan browser saat ini (Maret 2024):
Untuk gambaran umum yang diperbarui, lihat situs web ini.
Kode penuh dan minimalis untuk metode Conditional UI terlihat seperti ini:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Conditional UI</title> </head> <body> <input type="text" id="username" autocomplete="username webauthn" /> <script> async function passkeyLogin() { try { // retrieve the request options (incl. the challenge) from the WebAuthn server let options = await WebAuthnClient.getPublicKeyRequestOptions(); const credential = await navigator.credentials.get({ publicKey: options.publicKeyCredentialRequestOptions, mediation: "conditional", }); const userData = await WebAuthnClient.sendSignedChallenge(credential); window.location.href = "/logged-in"; } catch (error) { console.log(error); } } passkeyLogin(); </script> </body> </html>
Conditional UI hanya bekerja dengan kunci residen /
kredensial yang dapat ditemukan
Disarankan untuk menyediakan titik akhir server yang berbeda guna memulai
login Conditional UI.
Klien harus memenuhi beberapa persyaratan:
Untuk menghindari kesalahan, server harus terlebih dahulu menguji ketersediaan klien dengan fungsi ini:
Dalam lalu lintas nyata, masalah pendeteksian dan siklus hidup sering kali muncul sebagai
NotAllowedError atau AbortError. Gunakan
panduan kesalahan WebAuthn untuk klasifikasi yang diharapkan vs yang tidak terduga,
termasuk kesalahan asli
kunci sandi Credential Manager.
// source: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredential/isConditionalMediationAvailable#examples // Availability of `window.PublicKeyCredential` means WebAuthn is usable. if (window.PublicKeyCredential && PublicKeyCredential.isConditionalMediationAvailable) { // Check if conditional mediation is available. const isCMA = await PublicKeyCredential.isConditionalMediationAvailable(); if (isCMA) { // Call WebAuthn authentication start endpoint let options = await WebAuthnClient.getPublicKeyRequestOptions(); const credential = await navigator.credentials.get({ publicKey: options.publicKeyCredentialRequestOptions, mediation: "conditional", }); /* ... */ } }
Bidang masukan harus menerima token isi otomatis HTML, yang memberi sinyal kepada klien untuk mengisi kunci sandi pada permintaan yang sedang berlangsung. Selain kunci sandi, token isi otomatis dapat dipasangkan dengan token yang ada, mis. nama pengguna dan kata sandi:
<label for="name">Username:</label> <input type="text" name="name" autocomplete="username webauthn" /> <label for="password">Password:</label> <input type="password" name="password" autocomplete="current-password webauthn" />
Tidak ada skema basis data wajib atau standar untuk server WebAuthn. Namun, contoh skema basis data ini dapat digunakan untuk menyimpan informasi yang diperlukan dan menyediakan semua fungsionalitas server WebAuthn:
Atribut yang ditebalkan adalah wajib untuk implementasi minimal yang layak, sedangkan yang lain hanya dibutuhkan untuk fitur opsional, tetapi sangat membantu.
User DisplayName (user.displayName): Nama ramah pengguna dan mudah dibaca yang biasanya merupakan nama lengkap pengguna. Ini ditampilkan kepada pengguna, tetapi tidak digunakan selama autentikasi.
User Name (user.name): Nama unik dan dapat dibaca yang biasanya berupa alamat email atau nama pengguna. Ini dapat ditampilkan kepada pengguna, tetapi tidak digunakan selama autentikasi.
Relying Party ID (rpID) adalah domain yang disimpan di dalam kunci sandi, guna memastikan kunci sandi hanya berfungsi untuk domain yang benar (URL browser, lihat artikel ini untuk aplikasi asli). Selama autentikasi, rpID diperiksa terhadap URL browser dan hanya diizinkan dalam dua kasus ini:
Berikut contoh kombinasi yang (tidak) diizinkan:
Berikut adalah daftar alat & situs web yang berguna untuk mengimplementasikan kunci sandi.
chrome://device-log)Untuk strategi mengoptimalkan UX kunci sandi Anda melebihi implementasi teknis, lihat panduan kami tentang praktik terbaik pembuatan kunci sandi dan praktik terbaik masuk dengan kunci sandi.
Jika Anda ingin mengimplementasikan kunci sandi hanya dengan beberapa baris kode ke dalam aplikasi apa pun, Anda juga dapat menggunakan Corbado Complete (untuk aplikasi baru) atau Corbado Connect (untuk aplikasi lama)
Corbado adalah Authentication Intelligence Platform untuk tim CIAM yang menjalankan autentikasi consumer dalam skala besar. Kami membantu Anda melihat apa yang tidak bisa ditunjukkan oleh log IDP dan tool analytics generik: device, versi OS, browser, dan credential manager mana yang mendukung passkey; mengapa enrollment tidak menjadi login; di mana flow WebAuthn gagal; dan kapan update OS atau browser diam-diam merusak login — semuanya tanpa mengganti Okta, Auth0, Ping, Cognito, atau IDP internal Anda. Dua produk: Corbado Observe menambah observability untuk passkey dan metode login lainnya. Corbado Connect menghadirkan managed passkey dengan analytics terintegrasi (berdampingan dengan IDP Anda). VicRoads menjalankan passkey untuk 5M+ pengguna dengan Corbado (aktivasi passkey +80%). Bicara dengan pakar Passkey →
Conditional UI memerlukan pemeriksaan dukungan browser melalui
PublicKeyCredential.isConditionalMediationAvailable() sebelum memulai autentikasi.
Bidang input harus mencakup token HTML autocomplete="username webauthn" dan pengguna
harus memiliki pendaftaran kunci residen (kredensial yang dapat ditemukan). Titik akhir server
terpisah disarankan untuk menangani alur masuk Conditional UI.
Setidaknya, simpan ID Kredensial, yang dihasilkan oleh autentikator selama pendaftaran, dan User ID (user_id), yang dikembalikan sebagai userHandle di objek asersi. Gunakan ID Kredensial untuk mencari akun pengguna terkait dan membandingkan userHandle untuk memvalidasi autentikasi. Hindari menggunakan user.name untuk perbandingan karena dapat berubah dari waktu ke waktu.
Kunci residen (kredensial yang dapat ditemukan) disimpan di autentikator itu sendiri dan diambil selama autentikasi, yang diperlukan agar Conditional UI berfungsi. Kunci non-residen menyimpan ID kredensial di server dan mengirimkannya ke autentikator selama autentikasi. Bidang residentKey di authenticatorSelection mengontrol perilaku ini dengan nilai "required", "preferred" atau "discouraged".
Bidang userVerification mengontrol apakah autentikator harus memverifikasi pengguna selama masuk, yang menerima nilai "required", "preferred" (bawaan) atau "discouraged". Bila diatur ke "preferred", pengguna atau perangkatnya dapat sepenuhnya melewatkan verifikasi selama proses autentikasi, yang berpotensi melemahkan keamanan. Menyetelnya ke "required" memastikan verifikasi selalu dilakukan sebelum autentikasi selesai.
Lihat bagaimana Corbado cocok dengan peluncuran passkeys dan stack autentikasi Anda saat ini.
Jelajahi Console
Artikel terkait
Daftar isi