Panduan ini menjelaskan cara mendaftarkan kunci sandi secara otomatis dan otomatis untuk pengguna segera setelah login berbasis sandi berhasil, sehingga meminimalkan hambatan dan meningkatkan adopsi kunci sandi.
Momen Pemicu yang Tepat
Pembuatan kunci sandi otomatis (juga dikenal sebagai Pembuatan Bersyarat atau promosi pasca-login otomatis) HARUS dipicu hanya segera setelah login penuh yang berhasil dan melibatkan sandi.
- Jangan mencoba pembuatan bersyarat untuk alur tanpa sandi (misalnya, magic link, OTP SMS, atau penggabungan identitas).
- Jika autentikasi multi-faktor diperlukan, Anda HARUS menunggu hingga semua faktor berhasil sebelum memulai pembuatan bersyarat.
- Pastikan sesi pengguna yang valid dan terautentikasi aktif sebelum membuat permintaan ke endpoint pembuatan.
Langkah-Langkah Penerapan
1. Membatalkan Tindakan Isi Otomatis Sebelumnya
Jika halaman login menggunakan isi otomatis formulir (UI Bersyarat/Get), panggilan get kredensial aktif harus dibatalkan untuk mencegah konflik browser.
- Panggil
abortController.abort()padaAbortControlleryang dilampirkan ke permintaan isi otomatisnavigator.credentials.get()yang tertunda sebelum memanggilnavigator.credentials.create().
2. Deteksi Fitur
Tentukan apakah Pembuatan Bersyarat tersedia dengan memeriksa conditionalCreate dengan PublicKeyCredential.getClientCapabilities().
const capabilities = await PublicKeyCredential.getClientCapabilities();
if (capabilities.conditionalCreate) {
// Conditional create is available
}
3. Membuat kunci sandi dengan Pembuatan Bersyarat
- Teruskan
mediation: 'conditional'dalam opsinavigator.credentials.create(). Hal ini memberi sinyal kepada browser untuk menangani alur pembuatan kunci sandi secara otomatis di latar belakang atau secara kontekstual tanpa menampilkan dialog modal yang mengganggu. - Isi
excludeCredentialsdengan ID kredensial kunci sandi pengguna yang ada untuk menghindari pendaftaran kunci duplikat.
4. Penanganan Error Senyap
- Gabungkan dialog pembuatan kunci sandi (
navigator.credentials.create) dalam blok try/catch. Anda HARUS menangkap dan mengabaikan pengecualian umum yang ditampilkan kepada pengguna (InvalidStateError,NotAllowedError,AbortError) tanpa merender UI error apa pun kepada pengguna.
5. Verifikasi Kehadiran Pengguna Sisi Server
- Endpoint verifikasi sisi server HARUS melonggarkan persyaratan Kehadiran Pengguna (UP) (
requireUserPresence: false) HANYA saat memverifikasi kredensial yang dihasilkan oleh pemicu pembuatan bersyarat. Verifikasi kehadiran yang ketat harus tetap aktif untuk pembuatan eksplisit standar.
6. Menangani Verifikasi Server yang Gagal dengan baik
- Jika
navigator.credentials.create()berhasil, tetapi pengambilan verifikasi server menampilkan respons yang buruk (misalnya, verifikasi tanda tangan gagal), panggilPublicKeyCredential.signalUnknownCredential()untuk mencegah kredensial tanpa induk tetap berada di penyedia kunci sandi.
Contoh Kode
// optionsFetch and registerVerifyFetch are app-defined server endpoint requests
import { optionsFetch, registerVerifyFetch } from './api.js';
async function triggerConditionalCreate(loginAbortController) {
const capabilities = await PublicKeyCredential.getClientCapabilities();
if (capabilities.conditionalCreate !== true) {
return; // Platform does not support conditional creation
}
// 1. Abort any active autofill conditional-get controllers to clear the WebAuthn pipeline
loginAbortController.abort();
// 2. Fetch creation options signaling the backend that this is a conditional request
const creationOptionsJSON = await optionsFetch({ conditional: true });
const publicKey = PublicKeyCredential.parseCreationOptionsFromJSON(creationOptionsJSON);
let credential;
try {
// 3. Invoke silent credentials creation prompt
credential = await navigator.credentials.create({
publicKey,
mediation: 'conditional' // Silent background creation mediation
});
} catch (e) {
// 4. Silently swallow common WebAuthn browser exceptions
if (['InvalidStateError', 'NotAllowedError', 'AbortError'].includes(e.name)) {
return;
}
console.error('Unexpected conditional create error:', e);
return;
}
// 5. Server verification step using dedicated Try/Catch block
let encodedResponse = credential.toJSON();
try {
const response = await registerVerifyFetch(encodedResponse);
if (!response.ok) {
// If the server verification fails, clean up using Signal API
if (PublicKeyCredential.signalUnknownCredential) {
await PublicKeyCredential.signalUnknownCredential({
rpId, // RP ID must match the one defined on the server
credentialId: encodedResponse.id
});
}
}
} catch (serverErr) {
console.error('Verification network failure:', serverErr);
if (PublicKeyCredential.signalUnknownCredential) {
await PublicKeyCredential.signalUnknownCredential({
rpId, // RP ID must match the one defined on the server
credentialId: encodedResponse.id
});
}
}
}
Strategi Penggantian
Penggantian deteksi fitur kunci sandi
Selalu instal 'webauthn-polyfills' dan impor dalam konteks.
Pertimbangkan bahwa selama PublicKeyCredential didukung, PublicKeyCredential.getClientCapabilities juga didukung.
import 'webauthn-polyfills';
Penggantian Sinkronisasi Signal API
WebAuthn Signal API (webauthn-signals) adalah pengoptimalan progresif yang digunakan untuk menjaga pengelola sandi tetap sinkron dengan status kredensial server.
- Pengalaman Pengganti: Dibatasi melalui
if (PublicKeyCredential.signalUnknownCredential). Jika tidak didukung, sinkronisasi verifikasi latar belakang akan dilewati dengan baik tanpa menampilkan pengecualian browser.
Penggantian Serialisasi JSON yang Mudah
Selalu instal 'webauthn-polyfills' dan impor dalam konteks.
Pertimbangkan bahwa selama PublicKeyCredential didukung, PublicKeyCredential.parseCreationOptionsFromJSON dan PublicKeyCredential.prototype.toJSON juga didukung.
import 'webauthn-polyfills';