Buat pengalaman login yang memanfaatkan kunci sandi sekaligus tetap mengakomodasi pengguna sandi yang ada.
Kunci sandi menggantikan sandi dan membuat akun pengguna di web menjadi lebih aman, lebih sederhana, dan lebih mudah digunakan. Namun, transisi dari autentikasi berbasis sandi ke autentikasi berbasis kunci sandi dapat mempersulit pengalaman pengguna. Menggunakan isi otomatis formulir untuk menyarankan kunci sandi dapat membantu membuat pengalaman terpadu.
Mengapa menggunakan isi otomatis formulir untuk login dengan kunci sandi?
Dengan kunci sandi, pengguna dapat login ke situs hanya dengan menggunakan sidik jari, wajah, atau PIN perangkat.
Idealnya, tidak akan ada pengguna sandi dan alur autentikasi dapat semudah tombol login sekali. Saat pengguna mengetuk tombol, dialog pemilih akun akan muncul, pengguna dapat memilih akun, membuka kunci layar untuk memverifikasi dan login.
Namun, peralihan dari autentikasi berbasis sandi ke autentikasi berbasis kunci sandi dapat menjadi tantangan. Saat pengguna beralih ke kunci sandi, masih akan ada pengguna yang menggunakan sandi dan situs harus mengakomodasi kedua jenis pengguna tersebut. Pengguna sendiri tidak diharapkan untuk mengingat situs mana yang telah mereka alihkan ke kunci sandi, jadi meminta pengguna untuk memilih metode yang akan digunakan di awal akan menjadi UX yang buruk.
Kunci sandi juga merupakan teknologi baru. Menjelaskannya dan memastikan pengguna merasa nyaman menggunakannya dapat menjadi tantangan bagi situs. Kita dapat mengandalkan pengalaman pengguna yang sudah dikenal untuk mengisi otomatis sandi guna mengatasi kedua masalah tersebut.
UI Bersyarat
Untuk membuat pengalaman pengguna yang efisien bagi pengguna kunci sandi dan sandi, Anda dapat menyertakan kunci sandi dalam saran isi otomatis. Ini disebut UI kondisional dan merupakan bagian dari standar WebAuthn.
Segera setelah pengguna mengetuk kolom input nama pengguna, dialog saran isi otomatis akan muncul yang menandai kunci sandi yang disimpan beserta saran isi otomatis sandi. Kemudian, pengguna dapat memilih akun dan menggunakan kunci layar perangkat untuk login.
Dengan cara ini, pengguna dapat login ke situs Anda dengan formulir yang ada seolah-olah tidak ada yang berubah, tetapi dengan manfaat keamanan tambahan dari kunci sandi jika mereka memilikinya.
Cara kerjanya
Untuk mengautentikasi dengan kunci sandi, Anda menggunakan WebAuthn API.
Empat komponen dalam alur autentikasi kunci sandi adalah: pengguna:
- Backend: Server backend Anda yang menyimpan database akun yang menyimpan kunci publik dan metadata lainnya tentang kunci sandi.
- Frontend: Frontend Anda yang berkomunikasi dengan browser dan mengirim permintaan pengambilan ke backend.
- Browser: Browser pengguna yang menjalankan JavaScript Anda.
- Authenticator: Pengautentikasi pengguna yang membuat dan menyimpan kunci sandi. Ini mungkin di perangkat yang sama dengan browser (misalnya, saat menggunakan Windows Hello) atau di perangkat lain, seperti ponsel.
- Segera setelah pengguna membuka frontend, frontend akan meminta verifikasi dari backend untuk mengautentikasi dengan kunci sandi dan memanggil
navigator.credentials.get()
untuk memulai autentikasi dengan kunci sandi. Tindakan ini akan menampilkanPromise
. - Saat pengguna menempatkan kursor di kolom login, browser akan menampilkan dialog isi otomatis sandi termasuk kunci sandi. Dialog autentikasi akan muncul jika pengguna memilih kunci sandi.
- Setelah pengguna memverifikasi identitasnya menggunakan kunci layar perangkat, promise akan di-resolve dan kredensial kunci publik akan ditampilkan ke frontend.
- Frontend mengirim kredensial kunci publik ke backend. Backend memverifikasi tanda tangan dengan kunci publik akun yang cocok di database. Jika berhasil, pengguna akan login.
Mengautentikasi dengan kunci sandi melalui isi otomatis formulir
Saat pengguna ingin login, Anda dapat melakukan panggilan get
WebAuthn kondisional
untuk menunjukkan bahwa kunci sandi dapat disertakan dalam saran isi otomatis. Panggilan bersyarat
ke navigator.credentials.get()
API
WebAuthn tidak menampilkan UI dan tetap tertunda hingga
pengguna memilih akun untuk login dari saran isi otomatis. Jika pengguna memilih kunci sandi, browser akan me-resolve promise dengan kredensial, bukan mengisi formulir login. Kemudian, halaman tersebut bertanggung jawab untuk
membuat pengguna login.
Menganotasi kolom input formulir
Tambahkan atribut autocomplete
ke kolom input
nama pengguna, jika diperlukan.
Tambahkan username
dan webauthn
sebagai tokennya agar dapat menyarankan kunci sandi.
<input type="text" name="username" autocomplete="username webauthn" ...>
Deteksi fitur
Sebelum memanggil panggilan API WebAuthn kondisional, periksa apakah:
- Browser mendukung WebAuthn dengan
PublicKeyCredential
.
- Browser mendukung UI kondisional
WebAuthn dengan
PublicKeyCredential.isConditionalMediationAvailable()
.
// 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
}
}
Mengambil verifikasi login dari server RP
Ambil tantangan dari server RP yang diperlukan untuk memanggil
navigator.credentials.get()
:
challenge
: Tantangan yang dibuat server di ArrayBuffer. Hal ini diperlukan untuk mencegah serangan replay. Pastikan untuk membuat tantangan baru pada setiap upaya login dan mengabaikannya setelah durasi tertentu atau setelah upaya login gagal divalidasi. Anggap saja seperti token CSRF.allowCredentials
: Array kredensial yang dapat diterima untuk autentikasi ini. Teruskan array kosong agar pengguna dapat memilih kunci sandi yang tersedia dari daftar yang ditampilkan oleh browser.userVerification
: Menunjukkan apakah verifikasi pengguna yang menggunakan kunci layar perangkat adalah"required"
,"preferred"
, atau"discouraged"
. Setelan defaultnya adalah"preferred"
, yang berarti pengautentikasi dapat melewati verifikasi pengguna. Tetapkan ini ke"preferred"
atau hapus properti.
Memanggil WebAuthn API dengan tanda conditional
untuk mengautentikasi pengguna
Panggil navigator.credentials.get()
untuk mulai menunggu autentikasi pengguna.
// To abort a WebAuthn call, instantiate an `AbortController`.
const abortController = new AbortController();
const publicKeyCredentialRequestOptions = {
// Server generated challenge
challenge: ****,
// The same RP ID as used during registration
rpId: 'example.com',
};
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal,
// Specify 'conditional' to activate conditional UI
mediation: 'conditional'
});
rpId
: ID RP adalah domain dan situs dapat menentukan domain atau akhiran yang dapat didaftarkan. Nilai ini harus cocok dengan rp.id yang digunakan saat kunci sandi dibuat.
Jangan lupa untuk menentukan mediation: 'conditional'
agar permintaan bersifat kondisional.
Mengirim kredensial kunci publik yang ditampilkan ke server RP
Setelah pengguna memilih akun dan mengizinkan penggunaan kunci layar perangkat,
promise akan di-resolve dan menampilkan objek
PublicKeyCredential
ke frontend RP.
Promise dapat ditolak karena beberapa alasan. Anda harus menangani
error dengan semestinya, bergantung pada properti name
objek Error
:
NotAllowedError
: Pengguna telah membatalkan operasi.- Pengecualian lainnya: Terjadi error yang tidak terduga. Browser menampilkan dialog error kepada pengguna.
Objek kredensial kunci publik berisi properti berikut:
id
: ID yang dienkode base64url dari kredensial kunci sandi yang diautentikasi.rawId
: Versi ArrayBuffer dari ID kredensial.response.clientDataJSON
: ArrayBuffer data klien. Kolom ini berisi informasi seperti verifikasi login dan asal yang perlu diverifikasi oleh server RP.response.authenticatorData
: ArrayBuffer data pengautentikasi. Kolom ini berisi informasi seperti ID RP.response.signature
: ArrayBuffer tanda tangan. Nilai ini adalah inti kredensial dan perlu diverifikasi di server.response.userHandle
: ArrayBuffer yang berisi ID pengguna yang ditetapkan pada waktu pembuatan. Nilai ini dapat digunakan, bukan ID kredensial, jika server perlu memilih nilai ID yang digunakannya, atau jika backend ingin menghindari pembuatan indeks pada ID kredensial.authenticatorAttachment
: Menampilkanplatform
jika kredensial ini berasal dari perangkat lokal. Jika tidak,cross-platform
, terutama saat pengguna menggunakan ponsel untuk login. Jika pengguna perlu menggunakan ponsel untuk login, pertimbangkan untuk meminta mereka membuat kunci sandi di perangkat lokal.type
: Kolom ini selalu ditetapkan ke"public-key"
.
Jika Anda menggunakan library untuk menangani objek kredensial kunci publik di server RP, sebaiknya kirim seluruh objek ke server setelah mengenkodenya sebagian dengan base64url.
Memverifikasi tanda tangan
Saat Anda menerima kredensial kunci publik di server, teruskan ke library FIDO untuk memproses objek.
Cari ID kredensial yang cocok dengan properti id
(Jika Anda perlu menentukan akun pengguna, gunakan properti userHandle
yang merupakan user.id
yang Anda tentukan saat membuat kredensial). Lihat
apakah
signature
kredensial dapat diverifikasi dengan kunci publik yang disimpan. Untuk melakukannya, sebaiknya gunakan
library sisi server atau solusi, bukan menulis kode Anda sendiri. Anda dapat menemukan library open source di repositori GitHub awesome-webauth.
Setelah kredensial diverifikasi dengan kunci publik yang cocok, minta pengguna untuk login.
Ikuti petunjuk yang lebih mendetail di Autentikasi kunci sandi sisi server