使用 Signal API 讓密碼金鑰與伺服器上的憑證保持一致

發布日期:2024 年 11 月 12 日,上次更新日期:2024 年 11 月 29 日

WebAuthn Signal API 可讓信賴方傳送現有憑證信號給已連結的密碼金鑰提供者。有了這項功能,支援密碼金鑰的提供者就能更新或移除儲存空間中不正確或已撤銷的密碼金鑰,不再提供給使用者。

相容性

從 Chrome 132 版起,電腦版 Chrome 支援 Signal API。Google 密碼管理工具可以更新密碼金鑰,反映信號。如果是以 Chrome 擴充功能為基礎的密碼金鑰供應商,則可自行決定是否反映信號。

Android 版 Chrome 支援功能即將推出。

Safari 支援,但尚未實作。Firefox 尚未分享意見

背景

建立密碼金鑰 (可探索的憑證) 時,系統會將使用者名稱和顯示名稱等中繼資料,連同私密金鑰一併儲存至密碼金鑰供應商 (例如密碼管理工具),而公開金鑰憑證則會儲存至信賴方 (RP) 的伺服器。儲存使用者名稱和顯示名稱有助於使用者在系統提示時,識別要使用哪個密碼金鑰登入。如果使用者有多個密碼金鑰,且來自不同密碼金鑰供應商,這項功能就特別實用。

不過,如果密碼金鑰供應商的密碼金鑰清單與伺服器的憑證清單不一致,可能會造成混淆。

第一種情況是使用者刪除伺服器上的憑證,但密碼金鑰供應商的密碼金鑰不受影響。下次使用者嘗試使用密碼金鑰登入時,密碼金鑰提供者仍會向使用者顯示該密碼金鑰。不過,由於伺服器無法使用已刪除的公開金鑰進行驗證,因此登入嘗試會失敗。

第二種情況是使用者更新伺服器上的使用者名稱或顯示名稱。下次使用者嘗試登入時,密碼金鑰供應商中的密碼金鑰仍會顯示舊的使用者名稱和顯示名稱,即使伺服器已更新也是如此。理想情況下,兩者應同步。

信號 API

Signal API 是 WebAuthn API,可讓信賴方傳送密碼金鑰提供者的變更信號,解決上述問題。有三種方法:

指出憑證不存在的信號

const credential = await navigator.credentials.get({ ... });
const payload = credential.toJSON();

const result = await fetch('/login', { ... });

// Detect authentication failure due to lack of the credential
if (result.status === 404) {
  // Feature detection
  if (PublicKeyCredential.signalUnknownCredential) {
    await PublicKeyCredential.signalUnknownCredential({
      rpId: "example.com",
      credentialId: "vI0qOggiE3OT01ZRWBYz5l4MEgU0c7PmAA" // base64url encoded credential ID
    });
  } else {
    // Encourage the user to delete the passkey from the password manager nevertheless.
    ...
  }
}

RP 可透過使用 RP ID 和憑證 ID 呼叫 PublicKeyCredential.signalUnknownCredential(),通知密碼金鑰提供者指定的憑證已移除或不存在。密碼金鑰提供者會如何處理這項信號,取決於該提供者,但系統預期會移除相關聯的密碼金鑰,這樣使用者就無法使用密碼金鑰登入,因為相關聯的憑證不存在。

Browser Support

  • Chrome: 132.
  • Edge: 132.
  • Firefox: not supported.
  • Safari: 26.

Source

當因缺少憑證而無法透過密碼金鑰登入時,即可叫用這項 API。這樣一來,RP 就能防止使用者嘗試以沒有相關聯憑證的密碼金鑰登入。與 signalAllAcceptedCredentials 不同,這個方法不需要傳遞整個憑證 ID 清單,因此只要使用者未通過驗證,就應使用這個方法,避免揭露特定使用者的密碼金鑰數量。

從 Chrome 上的 Google 密碼管理工具刪除密碼金鑰時,系統會顯示對話方塊。
從 Chrome 的 Google 密碼管理工具刪除密碼金鑰時,系統會顯示對話方塊。

發出已儲存憑證清單的信號

// After a user deletes a passkey or a user is signed in.

// Feature detection
if (PublicKeyCredential.signalAllAcceptedCredentials) {
  await PublicKeyCredential.signalAllAcceptedCredentials({
    rpId: "example.com",
    userId: "M2YPl-KGnA8", // base64url encoded user ID
    allAcceptedCredentialIds: [ // A list of base64url encoded credential IDs
      "vI0qOggiE3OT01ZRWBYz5l4MEgU0c7PmAA",
      ...
    ]
  });
}

只要使用 RP ID、使用者 ID 和已儲存憑證的憑證 ID 清單呼叫 PublicKeyCredential.signalAllAcceptedCredentials(),RP 就能將儲存空間中剩餘的憑證告知密碼金鑰供應商。密碼金鑰提供者會如何處理這項信號,取決於該提供者,但系統預期會移除與這份清單不符的密碼金鑰,這樣使用者在登入時就不會看到相關聯憑證不存在的密碼金鑰。

Browser Support

  • Chrome: 132.
  • Edge: 132.
  • Firefox: not supported.
  • Safari: 26.

Source

使用者在 RP 上刪除密碼金鑰時,以及每次登入時,都應叫用這個 API,讓密碼金鑰提供者可以維持密碼金鑰清單的同步狀態。

Signal 更新了使用者名稱和顯示名稱

// After a user updated their username and/or display name
// or a user is signed in.

// Feature detection
if (PublicKeyCredential.signalCurrentUserDetails) {
  await PublicKeyCredential.signalCurrentUserDetails({
    rpId: "example.com",
    userId: "M2YPl-KGnA8", // base64url encoded user ID
    name: "a.new.email.address@example.com", // username
    displayName: "J. Doe"
  });
} else {
}

RP 可以透過 RP ID、使用者 ID、使用者名稱和顯示名稱呼叫 PublicKeyCredential.signalCurrentUserDetails(),將更新的使用者資訊告知密碼金鑰供應商。密碼金鑰供應商可自行決定如何處理這項信號,但使用者擁有的密碼金鑰應會更新為新的使用者資訊。

Browser Support

  • Chrome: 132.
  • Edge: 132.
  • Firefox: not supported.
  • Safari: 26.

Source

使用者更新使用者名稱或顯示名稱時,以及每次登入時,都可以呼叫這個 API,讓密碼金鑰提供者與伺服器同步處理這項資訊。

在 Chrome 的 Google 密碼管理工具中更新密碼金鑰中繼資料時,系統會顯示這個對話方塊。
在 Chrome 上的 Google 密碼管理工具中更新密碼金鑰中繼資料時,系統會顯示對話方塊。

摘要

Signal API 可協助您打造更優質的密碼金鑰體驗,避免發生非預期的登入失敗情況。信賴方可透過 Signal API 傳送現有憑證清單及其相關中繼資料,讓密碼金鑰提供者保持密碼金鑰同步。

如要進一步瞭解密碼金鑰,請參閱「使用密碼金鑰登入帳戶」。