Autentikasi Ulang Kunci Sandi

Fitur web: Autentikasi web

Panduan yang berfokus pada delta ini menjelaskan cara menerapkan autentikasi langkah-langkah atau verifikasi ulang untuk pengguna yang login sebelum mereka melakukan perubahan akun yang sensitif (misalnya, pembaruan sandi, transfer keuangan).

Arsitektur Delta Flow

Tidak seperti autentikasi reguler, autentikasi ulang kunci sandi membatasi dialog perintah kunci sandi secara ketat pada kredensial yang telah didaftarkan sebelumnya oleh pengguna yang login untuk mencegah pencampuran akun atau spoofing kunci sandi selama sesi aktif.

Sisi Server

Delta Pembuatan Opsi

Buat endpoint yang mengisi parameter kredensial yang diizinkan secara khusus untuk pengguna aktif yang diketahui:

Membatasi Kredensial: Isi array opsi allowCredentials dengan data PublicKeyCredentialDescriptor tertentu yang memetakan semua ID kredensial terdaftar untuk pengguna yang login. Jika dibiarkan kosong atau dihilangkan, kredensial yang dapat ditemukan akan digunakan, sehingga melanggar keamanan sesi.

// Node.js step-up options generation example
router.post("/api/reauth/options", enforceActiveSession, async (req, res) => {
  const userPasskeys = await db.findCredentialsByUserId(req.user.id);

  const options = {
    challenge: serverGeneratedBase64UrlChallenge, // Random challenge stored in user session
    rpId: "example.com",
    // Enforce allowance strictly limited to the user's credentials list
    allowCredentials: userPasskeys.map((cred) => ({
      type: "public-key",
      id: cred.id,
      transports: cred.transports, // Speeds up resolution by indicating platform transports
    })),
  };
  return res.json(options);
});

Delta Endpoint Verifikasi

Verifikasi pernyataan yang ditampilkan oleh klien:

Verifikasi Kepemilikan Akun: Endpoint verifikasi HARUS secara eksplisit memverifikasi bahwa ID kredensial autentikasi yang ditampilkan oleh klien di-resolve ke data kredensial tersimpan yang ID pengguna terkaitnya sama persis dengan pengguna aktif yang login (storedCredential.passkeyUserId === req.user.id). Jika kunci sandi yang valid dari pengguna yang berbeda ditampilkan, autentikasi HARUS segera ditolak.

Delta Alur Sisi Klien

Aplikasi memilih dari dua antarmuka autentikasi ulang, bergantung pada UI transaksi:

A. Alur Tombol (Tanpa Kolom Input)

Memicu autentikasi ulang saat pengguna menekan tombol "Verifikasi Identitas" atau "Lanjutkan Transaksi".

<button id="reauth-btn" data-testid="reauth-button">Confirm Transaction</button>
let reauthAbortController = new AbortController();

async function triggerButtonReauth() {
  // Abort any background suggestion flows to avoid passkey prompt collisions
  reauthAbortController.abort();
  reauthAbortController = new AbortController();

  const optionsResponse = await fetch("/api/reauth/options", {
    method: "POST",
  });
  const optionsJSON = await optionsResponse.json();
  const publicKey =
    PublicKeyCredential.parseRequestOptionsFromJSON(optionsJSON);

  try {
    const credential = await navigator.credentials.get({
      publicKey,
      signal: reauthAbortController.signal,
    });

    if (credential) {
      const encodedCredential = credential.toJSON();
      const verifyResponse = await fetch("/api/reauth/verify", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(encodedCredential),
      });

      if (verifyResponse.ok) {
        showTransactionSuccessUI();
      } else if (verifyResponse.status === 404 && PublicKeyCredential.signalUnknownCredential) {
        await PublicKeyCredential.signalUnknownCredential({
          rpId, // RP ID must match the one defined on the server
          credentialId: encodedCredential.id
        });
      }
    }
  } catch (err) {
    if (err.name === "NotAllowedError") {
      console.log("User cancelled reauthentication.");
    }
  }
}

document
  .getElementById("reauth-btn")
  .addEventListener("click", triggerButtonReauth);

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 Serialisasi JSON yang Mudah

Selalu instal 'webauthn-polyfills' dan impor dalam konteks. Pertimbangkan bahwa selama PublicKeyCredential didukung, PublicKeyCredential.parseRequestOptionsFromJSON dan PublicKeyCredential.prototype.toJSON juga didukung.

import 'webauthn-polyfills';