使用者驗證深入解析

本文件說明 userVerification 在 WebAuthn 中的情況,以及當在建立或驗證密碼金鑰時指定 userVerification 時,瀏覽器的行為。

WebAuthn 中的「使用者驗證」是什麼?

密碼金鑰的建構基礎採用公開金鑰密碼編譯技術。建立密碼金鑰後,系統會產生公開/私密金鑰組,供密碼金鑰提供者儲存私密金鑰,然後將公開金鑰傳回給依賴方 (RP) 伺服器來儲存。伺服器可以使用配對的公開金鑰,驗證由相同密碼金鑰簽署的簽名,藉此驗證使用者。公開金鑰憑證上的「使用者存在」(UP) 標記可證明在驗證期間,曾與裝置互動。

使用者驗證是選用的安全防護層,會在驗證期間聲明存在正確的人員,而非只有某些人,也就是使用者俱備的聲明。在智慧型手機上,通常是使用螢幕鎖定機制 (無論是生物特徵辨識,還是 PIN 碼或密碼)。系統是否會在驗證密碼金鑰時,將「UV」旗標記錄於驗證器資料中 (該旗標會在註冊和驗證密碼金鑰時傳回)

macOS iCloud 鑰匙圈使用者驗證對話方塊的螢幕截圖。對話方塊會提示使用者透過 Touch ID 登入,並顯示要求驗證的來源和使用者名稱。對話方塊右上方有標示為「取消」的按鈕。
macOS 中 iCloud 鑰匙圈的使用者驗證對話方塊。
Android 版 Chrome 使用者驗證對話方塊的螢幕截圖。對話方塊會提示使用者使用臉部辨識或指紋偵測功能驗證身分,並顯示要求驗證的來源。畫面左下方會顯示使用 PIN 碼進行驗證的選項。
Android Chrome 中的使用者驗證對話方塊。

伺服器上的 UP 和 UV 驗證方式

使用者狀態 (UP) 和使用者已驗證的 (UV) 布林值標記,會在驗證器資料欄位中向伺服器傳送信號。在驗證程序中,您可以利用儲存的公開金鑰驗證簽名,驗證驗證器資料欄位的內容。只要簽章有效,伺服器就能將標記視為正版。

驗證資料結構的說明。從左到右,資料結構的每個部分依序讀取了「RP ID HASH」(32 位元組)、「FLAGS」(1 位元組)、「COUNTER」(4 個位元組、big-endian uint32)、「ATTESTE CRED」。DATA (如有可變長度) 和「EXTENSIONS」(如果有的話,可變長度 (CBOR)。)展開「FLAGS」區段,顯示由左至右標示的潛在標幟清單,標籤為「ED」、「AT」、「0」、「BS」、「BE」、「UV」、「0」和「UP」。
公開金鑰憑證中的 Authenticator 資料欄位。

註冊密碼金鑰和進行驗證時,伺服器應檢查 UP 旗標是否為 true,以及 UV 旗標是 true 還是 false (取決於需求)。

指定 userVerification 參數

根據 WebAuthn 規格,RP 可以使用 userVerification 參數,在建立憑證及斷言時要求使用者驗證。它分別接受 'preferred''required''discouraged',這表示:

  • 'preferred' (預設):建議在裝置上使用使用者驗證方法,但如果沒有這個驗證方法,可以略過。如果執行使用者驗證,回應憑證會包含 true 的 UV 旗標值;如未執行 UV,則為 false
  • 'required':必須叫用裝置上可用的使用者驗證方法。如果沒有可用,則要求在本機會失敗。這表示回應憑證一律會傳回 UV 旗標設為 true
  • 'discouraged':不建議採用使用者驗證方法。不過,視裝置而定,系統仍可能會執行使用者驗證,且 UV 旗標可能包含 truefalse

建立密碼金鑰的程式碼範例:

const publicKeyCredentialCreationOptions = {
  // ...
  authenticatorSelection: {
    authenticatorAttachment: 'platform',
    residentKey: 'required',
    requireResidentKey: true,
    userVerification: 'preferred'
  }
};

const credential = await navigator.credentials.create({
  publicKey: publicKeyCredentialCreationOptions
});

密碼金鑰驗證的程式碼範例:

const publicKeyCredentialRequestOptions = {
  challenge: /* Omitted challenge data... */,
  rpId: 'example.com',
  userVerification: 'preferred'
};

const credential = await navigator.credentials.get({
  publicKey: publicKeyCredentialRequestOptions
});

您應該為「userVerification」選擇哪一個選項?

您應使用的 userVerification 值取決於應用程式需求,以及使用者體驗需求。

使用「userVerification='preferred'」的時機

如果您優先考量使用者體驗,而非保護,請使用 userVerification='preferred'

在許多環境中,使用者驗證流程會比保護措施更安全。舉例來說,如果 macOS 無法使用 Touch ID (因為裝置不支援、已停用或處於貝殼式模式),系統會要求使用者改為輸入系統密碼。這會造成不便,且使用者可能會完全放棄驗證程序。如果排除重新導向比較重要,請使用 userVerification='preferred'

在無法使用 Touch ID 時,macOS 顯示的密碼金鑰對話方塊螢幕截圖。對話方塊包含要求驗證的來源及使用者名稱等資訊。對話方塊右上方有標示為「取消」的按鈕。
在無法使用 Touch ID 時,macOS 會顯示密碼金鑰對話方塊。

使用 userVerification='preferred' 時,如果成功執行使用者驗證,UV 旗標為 true;如果略過使用者驗證,則為 false。舉例來說,在無法使用 Touch ID 的 macOS 上,系統會要求使用者點選按鈕來略過使用者驗證程序,而公開金鑰憑證則包含 false UV 旗標。

UV 旗標會在風險分析中列為信號。如果因其他因素導致登入嘗試有風險,建議您在未執行使用者驗證時向使用者提出額外的登入驗證問題。

使用「userVerification='required'」的時機

如果認為 UP 和 UV 都絕對必要,請使用 userVerification='required'

這個選項的缺點是,使用者登入時可能會遭遇更複雜的問題。舉例來說,如果 macOS 無法使用 Touch ID,系統會要求使用者輸入系統密碼。

透過 userVerification='required',您可以確保在裝置上進行使用者驗證。確認伺服器會驗證 UV 旗標為 true

結論

透過使用者驗證機制,由密碼金鑰負責的各方可以評估裝置擁有者登入的可能性。您可自行決定是否要求使用者驗證,或視備用登入機制對使用者流程的重要程度而定。確認伺服器會檢查 UP 旗標和 UV 旗標,以便進行密碼金鑰使用者驗證。