การตรวจสอบสิทธิ์ซ้ำด้วยพาสคีย์

คู่มือที่เน้นความแตกต่างนี้จะอธิบายรายละเอียดวิธีใช้การตรวจสอบสิทธิ์แบบยกระดับหรือการยืนยันอีกครั้งสำหรับผู้ใช้ที่ลงชื่อเข้าใช้ก่อนที่จะทำการเปลี่ยนแปลงบัญชีที่มีความละเอียดอ่อน (เช่น การอัปเดตรหัสผ่าน การโอนเงิน)

สถาปัตยกรรม Delta Flow

การตรวจสอบสิทธิ์ซ้ำด้วยพาสคีย์จะจำกัดข้อความแจ้งในกล่องโต้ตอบพาสคีย์ให้แสดงเฉพาะข้อมูลเข้าสู่ระบบที่ลงทะเบียนไว้ล่วงหน้าของผู้ใช้ที่เข้าสู่ระบบเท่านั้น ซึ่งแตกต่างจากการตรวจสอบสิทธิ์ทั่วไป ทั้งนี้เพื่อป้องกันการผสมบัญชีหรือการปลอมแปลงพาสคีย์ระหว่างเซสชันที่ใช้งานอยู่

ฝั่งเซิร์ฟเวอร์

เดลต้าของการสร้างตัวเลือก

สร้างปลายทางที่ป้อนข้อมูลพารามิเตอร์ข้อมูลเข้าสู่ระบบที่อนุญาตสำหรับผู้ใช้ที่ใช้งานอยู่และรู้จักโดยเฉพาะ ดังนี้

จำกัดข้อมูลเข้าสู่ระบบ: ป้อนข้อมูลอาร์เรย์ allowCredentials options ด้วยระเบียน PublicKeyCredentialDescriptor ที่เฉพาะเจาะจงซึ่งจับคู่รหัสข้อมูลเข้าสู่ระบบที่ลงทะเบียนทั้งหมดสำหรับผู้ใช้ที่ลงชื่อเข้าใช้ การเว้นว่างหรือละเว้นช่องนี้จะทำให้กลับไปใช้ข้อมูลเข้าสู่ระบบที่ค้นพบได้ ซึ่งละเมิดความปลอดภัยของเซสชัน

// 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);
});

เดลต้าปลายทางการยืนยัน

ยืนยันการยืนยันที่ไคลเอ็นต์แสดงผล:

ยืนยันการเป็นเจ้าของบัญชี: ปลายทางการยืนยันต้องยืนยันอย่างชัดเจนว่ารหัสข้อมูลรับรองที่ผ่านการตรวจสอบสิทธิ์แล้วซึ่งไคลเอ็นต์แสดงผลนั้นตรงกับระเบียนข้อมูลรับรองที่จัดเก็บไว้ซึ่งมีรหัสผู้ใช้ที่เชื่อมโยงตรงกับผู้ใช้ที่ลงชื่อเข้าใช้และใช้งานอยู่ (storedCredential.passkeyUserId === req.user.id) หากระบบแสดงผลพาสคีย์ที่ถูกต้องของผู้ใช้รายอื่น การตรวจสอบสิทธิ์ต้องถูกปฏิเสธทันที

เดลต้าของโฟลว์ฝั่งไคลเอ็นต์

แอปพลิเคชันจะเลือกจากอินเทอร์เฟซการตรวจสอบสิทธิ์ซ้ำ 2 แบบ โดยขึ้นอยู่กับ UI ของธุรกรรม ดังนี้

ก. ขั้นตอนการใช้ปุ่ม (ไม่มีช่องป้อนข้อมูล)

ทริกเกอร์การตรวจสอบสิทธิ์ซ้ำเมื่อผู้ใช้กดปุ่ม "ยืนยันตัวตน" หรือ "ดำเนินการทำธุรกรรมต่อ"

<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);

กลยุทธ์สำรอง

ฟีเจอร์สำรองสำหรับการตรวจหาฟีเจอร์พาสคีย์

ติดตั้ง "webauthn-polyfills" และนำเข้าในบริบทเสมอ พิจารณาว่าตราบใดที่ระบบรองรับ PublicKeyCredential ระบบก็จะรองรับ PublicKeyCredential.getClientCapabilities ด้วย

import 'webauthn-polyfills';

Easy JSON Serialization Fallback

ติดตั้ง "webauthn-polyfills" และนำเข้าในบริบทเสมอ โปรดทราบว่าตราบใดที่ระบบรองรับ PublicKeyCredential ระบบก็จะรองรับ PublicKeyCredential.parseRequestOptionsFromJSON และ PublicKeyCredential.prototype.toJSON ด้วย

import 'webauthn-polyfills';