為了在多個網域中提供流暢的情境內驗證,機構通常會在 iframe 中嵌入登入頁面。不過,在第三方頁框內載入驗證環境,會讓使用者曝露於點擊劫持 (UI 重新修飾) 和未經授權的憑證建立等重大威脅。為降低這些風險,瀏覽器預設會停用跨來源 iframe 中的 WebAuthn。如要安全解除這項限制,必須採用有效的縱深防禦通訊協定。
找出威脅模型
在子框架中啟用密碼金鑰 (WebAuthn) 前,請先瞭解您要防範的濫用情境:
- 透過隱藏的 iframe 插入追蹤程式:攻擊者會透過信任網站上的廣告或小工具,從自己的網域觸發 WebAuthn 提示,誘騙使用者授權密碼金鑰,但使用者不會看到相關背景資訊。這會將使用者的身分連結至攻擊者控制的帳戶,以收集資料。
- 視覺疊加和點擊劫持 (UI 重新修飾):惡意父項網頁會使用標準 CSS 讓驗證 iframe 隱形,並疊加假的 UI 元素,竊取觸發驗證流程的點擊。如果使用者不慎完成提示,可能會導致工作階段遭劫持或強制執行未經授權的動作。
為防範這些威脅,請遵循下列最佳做法:
頂層文件 (頂端框架):
嵌入式文件 (iframe):
兩份文件都必須:
使用權限政策啟用委派
根據預設,瀏覽器會封鎖跨來源 iframe 中的 WebAuthn 存取權。權限政策是統一的網頁平台機制,可讓頂層文件明確將這些強大功能委派給特定信任的第三方來源。
功能權杖
WebAuthn 使用兩種不同的權杖:
publickey-credentials-get:授權密碼金鑰登入流程 (navigator.credentials.get())。publickey-credentials-create:授權密碼金鑰註冊流程 (navigator.credentials.create())。
啟用規定
如要啟用這些功能,父項伺服器回應和用戶端標記都必須符合下列條件:
- Permissions-policy HTTP 回應標頭 (父項伺服器網站): 父項網頁必須使用結構化欄位語法,在 HTTP 回應標頭中宣告允許的來源。
Permissions-Policy: publickey-credentials-get=(self "https://embedded-auth.example.com")
權限政策:publickey-credentials-get 相容性:
權限政策:publickey-credentials-create 相容性:
- HTML
allow屬性:在 HTML 標記中,<iframe>元素也必須宣告啟用這項功能。
<iframe src="https://embedded-auth.example.com?nonce=deadbeef12345678&client=https%3A%2F%2Fembedded-auth.example.com" allow="publickey-credentials-get"></iframe>
iframe allow="publickey-credentials-get" 相容性:
Browser Support
iframe allow="publickey-credentials-create" 相容性:
Browser Support
啟用分割的第三方 Cookie
為確保驗證流程穩定運作,必須在嵌入的跨原始來源 iframe 中建立並維護工作階段。現代瀏覽器改用嚴格的第三方 Cookie 限制後,標準持續性機制通常會預設遭到封鎖,可能需要呼叫 Storage Access API 才能取得存取權。
如要解決這些障礙,請使用 SameSite:
None、Secure 和 Partitioned 屬性設定工作階段 Cookie。這個統一的平台機制可確保 iframe 內的狀態持續存在,同時遵守瀏覽器層級的隱私權控制項。
設定SameSite: None
SameSite:
None
明確標記 Cookie 以供跨網站存取,允許 Cookie 隨第三方環境 (例如 iframe) 發出的要求傳送。在跨源情境中,這個屬性是 Cookie 正常運作的必要條件,但必須與 Secure 屬性合併,才能獲得新版瀏覽器接受。
設定Partitioned
Partitioned 屬性會將 Cookie 納入 CHIPS (具有獨立分區狀態的 Cookie),讓 Cookie 能為每個頂層網站分別儲存。這樣可確保 Cookie 仍可在特定第三方 iframe 環境中存取,並在不啟用跨網站追蹤的情況下,維持工作階段狀態。使用者必須在不同網站上,為每個嵌入內容重新登入。
使用內容安全政策保護端點
權限政策會決定 iframe「能否」執行 WebAuthn,而內容安全政策 (CSP) 則會決定「誰」可以代管 iframe。
對於驗證端點,請務必確保只有授權的合作夥伴網站或您自己的資源可以載入登入子框架,在未經授權的點擊劫持嘗試載入 UI 前就加以封鎖。
使用frame-ancestors
frame-ancestors
指令
會定義可嵌入網站的有效上層網頁。將網域新增至這項指令,即可允許網域嵌入登入子框架。
Content-Security-Policy: frame-ancestors 'self' https://parent-site.example.com;
內容安全政策:frame-ancestors 相容性:
設定X-Frame-Options
舊版 X-Frame-Options 標頭支援類似功能,但僅支援二進位選項 (DENY 或 SAMEORIGIN)。如果瀏覽器不支援 CSP,請同時設定 CSP frame-ancestors 和 X-Frame-Options: DENY。如果支援 CSP,系統一律會優先採用。
X-Frame-Options: DENY
X-Frame-Options 相容性:
信任,但仍須在伺服器端驗證
瀏覽器的用戶端檢查會評估意圖和權限,但伺服器才是信任度的最終仲裁者。在 RP 伺服器上驗證回應,確保內容有效且已簽署。
用戶端資料酬載
WebAuthn 用戶端資料包含專門設計的參數,可協助您驗證 iframe 中提出的要求環境:
crossOrigin(布林值):指出是否在跨來源 iframe 中叫用 WebAuthn API。如果您的架構採用 iframe,伺服器必須強制執行這個旗標為true。topOrigin(字串):頂層瀏覽情境的來源 (瀏覽器網址列中顯示的內容)。伺服器必須根據已知的授權父項來源清單驗證這項資訊。
驗證檢查清單
如要在伺服器上驗證驗證器回應,請執行下列步驟:
- 剖析並解碼驗證器回應中的簽署
collectedClientData。 - 確認
type與儀式相符 (webauthn.get或webauthn.create)。 - 確認使用者在場並簽名。
- 如果要求是從 iframe 結構發出:
- 強制執行
crossOrigin === true。 - 強制
topOrigin與授權的父項來源清單相符。
- 強制執行
使用 postMessage() 安全地建立工作階段
如要穩定建立工作階段,iframe 必須使用 postMessage() 將驗證權杖傳回父項網頁,讓父項在自己的第一方情境中管理工作階段狀態。
安全的工作流程
如要建立安全連線,請按照下列工作流程操作:
- 確認 iframe
src網址包含nonce和origin查詢參數:- 請為
nonce使用隨機值。nonce可做為安全驗證權杖,確保從 iframe 收到的驗證符記,確實與父項網頁啟動的特定工作階段相符。 - 請使用父框架網域做為
origin。origin參數會指定父項網頁的來源,讓 iframe 安全地識別已嵌入的授權情境。
- 請為
- iframe 會透過自己的伺服器完成 WebAuthn 驗證。
iframe 伺服器會核發權杖 (例如 JWT),其中包含
nonce,並轉送至父項頁面。// Extract nonce and origin from the URL params const urlParams = new URLSearchParams(window.location.search); const nonce = urlParams.get('nonce'); const origin = urlParams.get('origin'); if (!nonce || !origin) { alert('Nonce or origin is missing in the URL'); return; } // Create a JWT const response = await post('/createToken', { nonce, origin }); const token = response.token; // Post the JWT to the parent frame window.parent.postMessage({ token }, origin);上層頁面會監聽
message事件、驗證傳送者來源,並驗證權杖。window.addEventListener("message", (event) => { if (event.origin !== "https://embedded-auth.example.com") return; // Verify the received JWT const result = await post('/verifyIdToken', { token: event.data.token, origin: provider.origin, }); });如果 JWT 驗證成功,父項頁面會保留工作階段。
傳送者和接收者共同承擔安全責任:
- 傳送者 (iframe):傳送訊息時,請務必指定嚴格的目標來源 (請勿使用
"*")。 - 接收者 (家長):接收訊息時,請務必驗證
event.origin,以免遭到來源詐欺。
結論
安全使用 iframe 的關鍵在於:啟用權限政策、限制內容安全政策 (CSP)、使用已分割的第三方 Cookie 持續工作階段、伺服器端驗證用戶端情境,以及使用 postMessage() 移交情境感知的會話。
如要進一步瞭解相關主題,請追蹤 Google 的 Chrome 開發人員網誌,並參閱 Chrome 開發人員身分說明文件中的更多資源。