題幹與適用情境
你負責一個已有密碼登入的網站,準備加入 Passkey。產品希望使用者在支援的瀏覽器中使用系統解鎖或安全金鑰登入,同時保留容易理解的降級與恢復路徑。請設計前端與伺服器的協作,說明 navigator.credentials.create()、navigator.credentials.get()、challenge、RP ID、origin 驗證與憑證管理邊界。
WebAuthn 是瀏覽器與 authenticator 之間的公開金鑰驗證 API;私鑰留在 authenticator,網站保存公鑰。前端只負責取得伺服器選項、呼叫瀏覽器 API、序列化結果與呈現狀態,簽章驗證、challenge 消費與帳號綁定必須在伺服器完成。
面試官考察點
強回答會把註冊與登入拆成兩個有狀態的短流程:伺服器產生一次性、不可預測的 challenge,前端呼叫 authenticator,伺服器驗證回傳的 challenge、origin、RP ID、簽章與計數器,再建立工作階段。還要涵蓋 HTTPS 安全情境、使用者取消、逾時、裝置遷移、多個憑證與恢復,不把「有 Face ID 就成功」當成協定設計。
面試官會特別看你是否理解條件式自動填入只是 UX 能力,不能繞過伺服器驗證;以及為什麼刪除伺服器憑證後,還要用 WebAuthn signal API 讓 authenticator 更新狀態。
回答前需要釐清的問題
支援範圍與帳戶策略
確認目標瀏覽器、行動端與桌面端,是否允許跨裝置同步的 discoverable credential,是否仍保留密碼或安全金鑰。不同策略會改變 residentKey、userVerification、憑證選擇與協助文字。
網域與部署拓撲
確認正式網域、登入子網域、iframe、反向代理與多租戶網域。RP ID 必須是目前 origin 的有效關聯網域;如果環境從預覽網域切到正式網域,不能想當然地共用同一組設定。
恢復與高風險操作
問清楚使用者遺失所有 authenticator 時如何證明身分,以及重設後是否要撤銷既有工作階段、通知使用者並延遲高風險操作。恢復是身分生命週期的一部分,不能只在前端顯示「改用密碼」。
30 秒回答框架
「註冊和登入都由伺服器先產生一次性、不可預測的 challenge,前端只把 options 交給 WebAuthn API。註冊時伺服器驗證回傳的 challenge、origin、RP ID、attestation 策略與公鑰,再把 credential ID 綁定帳戶;登入時驗證 assertion 的簽章、challenge、RP ID、origin 與簽章計數器,成功後才建立工作階段。前端明確區分不支援、使用者取消、逾時與伺服器拒絕;支援條件式 mediation 時提供自動填入,但不依賴它。使用者遺失裝置時要求經過風控的恢復流程、撤銷舊工作階段並允許註冊新憑證。」
分步驟深入解答
第一步:讓伺服器產生 challenge
註冊或登入頁面先向伺服器要求建立流程,伺服器產生至少 16 位元組的隨機 challenge,保存雜湊、帳戶、用途、到期時間與已消費狀態。challenge 不能由前端產生或重複使用,否則攻擊者可以把舊 assertion 搬到另一個流程。伺服器回傳符合目前 RP 的 publicKey options,前端不要自行修改安全欄位。
第二步:設計註冊流程
前端在 HTTPS 安全情境呼叫 navigator.credentials.create()。註冊選項包含 RP、使用者 ID、顯示名稱、允許的公鑰演算法、使用者驗證偏好與 discoverable credential 策略。Promise 成功後,前端把 credential ID、client data、attestation response 與必要擴充序列化送回伺服器;私鑰不離開 authenticator。
第三步:伺服器驗證註冊結果
伺服器檢查 challenge 與流程記錄一致、origin 屬於允許集合、RP ID hash 正確、簽章與公鑰演算法符合策略,並依隱私與相容目標決定是否驗證 attestation。成功後只保存公鑰、credential ID、使用者帳戶、簽章計數器與裝置標籤等必要資料。不能把整個原始物件或可識別裝置資訊無限期保存。
第四步:設計登入與條件式自動填入
登入時伺服器產生新的 challenge,前端呼叫 navigator.credentials.get() 並提交 assertion。伺服器驗證 challenge、origin、RP ID、簽章與計數器,再依 credential ID 找到帳戶。支援條件式 mediation 時,頁面可以在使用者聚焦使用者名稱輸入框後要求可發現憑證,讓瀏覽器把 Passkey 放進自動填入;這只是發現憑證的互動模式,不能省略完整驗證。
第五步:處理前端狀態與失敗
使用者取消、逾時、瀏覽器不支援、權限策略阻止與伺服器拒絕要分別記錄為容易理解的狀態。AbortController 可在使用者離開頁面或重複點擊時取消尚未完成的呼叫,避免舊 Promise 覆蓋新狀態。前端不要顯示簽章、credential ID 或伺服器內部錯誤,也不要在失敗時自動把未完成註冊標記為成功。
第六步:恢復、撤銷與憑證管理
帳戶頁面應列出憑證名稱、建立時間與最近使用時間,允許使用者刪除單一憑證。伺服器刪除後,下一次收到未知 credential ID 可以呼叫 PublicKeyCredential.signalUnknownCredential();成功登入後也可用 signalAllAcceptedCredentials() 同步伺服器仍接受的 ID。遺失所有憑證時走密碼加風險驗證、已驗證信箱或人工支援等恢復路徑,撤銷舊工作階段後再註冊新 Passkey。
第七步:驗證與演進
測試至少涵蓋不同瀏覽器、平台 authenticator、跨裝置同步、安全金鑰、取消、逾時、origin 錯誤、過期 challenge、重複 challenge、計數器異常與恢復後的舊憑證。設定透過能力偵測與伺服器策略下發,避免用 user-agent 猜測。新擴充採用可選欄位與回退 UI,不讓未知擴充改變伺服器的核心驗證規則。
高品質示範回答
我會把 Passkey 當作伺服器驅動的公開金鑰驗證流程。使用者按下註冊時,前端先向伺服器要求一次性 challenge 和 publicKey options,再在 HTTPS 頁面呼叫 WebAuthn。回傳結果只由伺服器驗證:challenge、origin、RP ID、簽章、公鑰演算法與必要 attestation 都通過後,伺服器保存 credential ID、公鑰、計數器與帳戶關聯。私鑰始終留在 authenticator。
登入流程同樣先由伺服器產生新的 challenge。前端呼叫 navigator.credentials.get(),收到 assertion 後提交給伺服器;伺服器驗證簽章、challenge、origin、RP ID 與計數器,成功後才建立工作階段。支援條件式 mediation 時,我會在使用者與使用者名稱輸入框互動後提供 Passkey 自動填入,但仍走相同的伺服器驗證。
前端把不支援、使用者取消、逾時與拒絕分開處理,離開頁面時取消未完成呼叫。帳戶設定提供憑證清單與刪除功能;刪除後同步 WebAuthn signal,讓瀏覽器不再繼續建議未知憑證。遺失裝置時需要風控恢復、撤銷舊工作階段、通知使用者並註冊新憑證。測試涵蓋跨平台 authenticator、錯誤 origin、過期或重複 challenge、計數器異常、瀏覽器回退與恢復後舊憑證,確保 UX 變化不會削弱協定驗證。
常見錯誤
- 錯誤表現: 前端自己產生 challenge 或把它寫在頁面常數。→ 失敗原因: 攻擊者可以重放舊 assertion,伺服器也無法確認流程新鮮度。→ 修正方法: 由伺服器產生、短期保存、一次消費並綁定帳戶與用途。
- 錯誤表現: 只檢查 Promise 成功就登入。→ 失敗原因: 瀏覽器回傳物件不等於伺服器已驗證 origin、RP ID 與簽章。→ 修正方法: 伺服器完成完整 assertion 驗證,前端只依結構化結果更新 UI。
- 錯誤表現: 用 user-agent 判斷是否支援 Passkey。→ 失敗原因: 瀏覽器版本、平台 authenticator 與權限策略會變動,靜態判斷容易誤導使用者。→ 修正方法: 使用能力 API 和伺服器策略,失敗時提供明確的密碼或安全金鑰路徑。
- 錯誤表現: 刪除資料庫 credential 後不處理裝置端狀態。→ 失敗原因: authenticator 仍認為憑證存在,使用者會反覆看到無法使用的選項。→ 修正方法: 在合適的驗證狀態呼叫 WebAuthn signal API,並提供重新註冊入口。
追問及應對
追問一:為什麼 RP ID 不能直接寫成任意 API 網域?
RP ID 必須與目前 origin 的網域關聯,並由瀏覽器與伺服器共同驗證。寫成不受目前頁面控制的網域會導致建立流程失敗或擴大信任範圍。多租戶情境要為每個可信網域明確設定,不能使用用戶端傳入的任意字串。
追問二:使用者在手機註冊後,桌面瀏覽器沒有這把鑰匙怎麼辦?
如果產品允許同步的 discoverable credential,瀏覽器和憑證管理器可以在裝置間提供同一帳戶的 Passkey;否則提供跨裝置 QR 或安全金鑰流程。前端應顯示「此裝置不可用」的可操作提示,伺服器仍按相同 challenge 和 assertion 規則驗證,不因跨裝置 UX 而跳過 origin 檢查。
追問三:簽章計數器倒退是否立即鎖號?
先區分平台同步憑證、備份恢復與真正的複製風險。計數器異常應觸發風險標記、追加驗證與通知,而不是在沒有上下文時永久鎖死帳戶。高價值動作可以要求另一把已登記憑證或人工複核,並記錄處理結果供後續策略調整。
追問四:恢復流程會不會讓 Passkey 安全性變弱?
會,如果恢復只依賴可能被接管的信箱連結。恢復應採用分級風控、工作階段撤銷、冷卻期、通知與高風險操作延遲;成功後讓使用者登記新憑證並清理舊憑證。面試中要說明可用性與接管風險的取捨,而不是承諾「永遠不會丟號」。