我们的指南将带您了解如何在跨源 iframe 中创建 Passkey 并用其登录。学习 WebAuthn 中的 iframe、安全策略及具体实现方法。
Vincent
Created: July 15, 2025
Updated: July 16, 2025
See the original blog version in English here.
Our mission is to make the Internet a safer place, and the new login standard passkeys provides a superior solution to achieve that. That's why we want to help you understand passkeys and its characteristics better.
浏览器 | 跨源登录 ( navigator.credentials.get ) | 跨源创建 ( navigator.credentials.create ) |
---|---|---|
Chrome/Edge | ✅ Chrome 84 (2020 年 7 月) | ✅ Chrome 123 (2024 年 3 月) |
Firefox | ✅ Firefox 118 (2023 年 9 月) | ✅ Firefox 123 (2024 年 2 月) |
Safari | ✅ Safari 15.5 (2022 年 5 月) | ❌ 不支持 |
图例
✅ = 支持 ❌ = 不支持
每周,都有越来越多的组织宣布推出 Passkey(例如最近的 Visa、Mastercard 或 Vercel)。随着其他公司的开发者和产品经理纷纷效仿这些先行者,更多关于 Passkey 实现的用例也得到了讨论。
我们经常被问到的一个问题是 Passkey 在 iframe 中如何工作,因为 iframe 在现代 Web 开发中被广泛用于无缝嵌入来自不同来源的内容。在 Passkey 和 WebAuthn 的背景下,iframe 带来了一系列独特的挑战,尤其是在安全和用户交互方面。
这篇博文将提供一份关于在 iframe 中使用 Passkey 和 WebAuthn 的综合指南。我们将:
读完本文后,您将清楚地了解如何在 iframe 中利用 Passkey。
iframe,即内联框架,是一种 HTML 元素,允许开发者在当前文档中嵌入另一个 HTML 文档。这项功能被广泛用于将外部来源的内容(如视频、地图和其他网页)整合到网站中。
让我们来看看不同类型的 iframe。
基础 iframe 是最常用的类型。它只是简单地将另一个 URL 的内容嵌入到当前页面中。
<iframe src="https://example.com"></iframe>
这种基础 iframe 通常用于在网页中包含静态内容,比如一篇文章。
响应式 iframe 旨在根据屏幕尺寸或其所在的容器调整自身大小。这确保了嵌入的内容在所有设备上(包括桌面、平板和手机)都能良好显示。
<iframe src="https://example.com" style="width: 100%; height: 500px;"></iframe>
也可以使用 CSS 媒体查询使 iframe 根据视口大小动态调整。
安全或沙盒化 iframe 限制了在 iframe 内可以执行的操作。这对于嵌入来自不受信任来源的内容或增强安全性非常有用。
<iframe src="https://example.com" sandbox></iframe>
sandbox 属性可以包含多种限制,例如:
<iframe src="https://example.com" sandbox="allow-scripts allow-same-origin"></iframe>
sandbox 属性允许脚本运行,但限制了潜在的危险操作,如表单提交或插件使用。
跨源 iframe 嵌入来自不同域的内容。它们通常用于集成第三方服务,例如支付网关或社交媒体小部件。由于安全限制,这些 iframe 对嵌入页面的内容访问权限有限,反之亦然。
跨源(Cross-origin)意味着加载的内容来自不同的源,而源是由协议(scheme)、主机(domain)和端口号(port
number)的组合定义的。例如,https://example.com
和 http://example.com
被认为是不同的源,因为它们使用不同的协议(HTTP vs. HTTPS)。
同样,子域与其父域也被视为独立的源。例如,https://example.com
和
https://sub.example.com
是跨源的,尽管它们共享相同的基础域。这种分离确保了一个子域的脚本和数据不能在没有明确许可的情况下直接与另一个子域的脚本和数据交互,从而增强了安全性。
Igor Gjorgjioski
Head of Digital Channels & Platform Enablement, VicRoads
Corbado proved to be a trusted partner. Their hands-on, 24/7 support and on-site assistance enabled a seamless integration into VicRoads' complex systems, offering passkeys to 5 million users.
众多企业信赖 Corbado,通过 Passkey 保护用户并实现更无缝的登录体验。立即获取您的免费 Passkey 咨询。
获取免费咨询以下是一些示例,用以说明跨源和同源的概念:
跨源示例:
将来自 https://payment.example.com 的内容嵌入到托管在 https://www.mystore.com 的网页中。它们是跨源的,因为它们的域名不同。
同源示例:
将来自 https://www.example.com/shop 的内容嵌入到托管在 https://www.example.com/blog 的网页中。它们是同源的,因为它们共享相同的协议、主机和端口。
跨源 iframe 与基础 iframe 的不同之处在于其来源是另一个域,而同站 iframe 的来源与嵌入它的域相同。
<iframe src="https://anotherdomain.com"></iframe>
在 iframe 中使用 Passkey 带来了一些新的功能和限制,开发者需要理解这些,主要围绕设置正确的权限和确保嵌入上下文中的安全用户交互。
过去,由于安全考虑,Web Authentication API 在跨源 iframe 中默认是禁用的。这一限制意味着开发者必须重定向用户或使用弹出窗口进行身份验证,导致用户体验不够流畅。
在 Passkey / WebAuthn 中,有两个核心操作(也称为“仪式”):
这两种操作在跨源 iframe 中的支持程度过去和现在都不同:
起初,通过跨源 iframe 登录是可行的,但跨源创建尚不支持,因为当时还没有人提出这样的用例。
最近的进展(例如 Chrome 123)在特定条件下引入了对创建跨源 iframe Passkey 的支持。然而,截至 2024 年 5 月,并非所有浏览器都完全支持通过跨源 iframe 创建 Passkey,尽管大多数浏览器都支持登录。
此外,跨源 iframe 支持(用于注册和认证操作)已经被纳入正在进行的 WebAuthn Level 3 规范中。一些浏览器(如 Safari)仍需跟上规范的步伐。不幸的是,苹果公司尚未宣布是否以及何时允许在 Safari 中进行 Passkey 的跨源注册。这将消除在跨源 iframe 中使用 Passkey 的最大技术限制。
在博文的后续部分,我们假设使用的是跨源 iframe。
下表概述了浏览器/标准对 iframe 认证和通过 Passkey 在跨源 iframe 上下文中登录的支持情况:
浏览器/标准 | 第一方上下文 | 第三方上下文 |
---|---|---|
WebAuthn Level 2 中要求 | ✔️ | ✔️ |
WebAuthn Level 3 中要求 | ✔️ | ✔️ |
Chrome 中已实现 | ✔️ | ✔️ |
Firefox 中已实现 | ✔️ | ✔️ |
Safari 中已实现 | ✔️ | ✔️ |
截至 2024 年 5 月,并非所有浏览器都支持在跨源 iframe 中创建 Passkey。下表概述了浏览器/标准对在跨源 iframe 中注册/创建 Passkey 的支持情况:
浏览器/标准 | 第一方上下文 | 第三方上下文 |
---|---|---|
WebAuthn Level 2 中要求 | ✔️ 详情 | ❌ |
WebAuthn Level 3 中要求 | ✔️ 详情 | ✔️ 详情 |
Chrome 中已实现 | ✔️ 详情 | ✔️ 详情 |
Firefox 中已实现 | ✔️ 详情 | ✔️ 详情 |
Safari 中已实现 | ✔️ 详情 | 等待实现信号 |
如果您对这一发展和支持的更多背景信息感兴趣,我们建议您查看这个 GitHub issue 和这个 Pull Request。
支持在跨源 iframe 中使用 Passkey 有两个主要用例。
在跨源 iframe 中启用 Passkey 对于涉及多个域但应使用相同用户账户的联合身份认证场景至关重要。
让我们来看以下场景。您是一家像 KAYAK 这样的跨国公司,为不同地区设有不同的域名:
然而,您有一个中央身份管理系统,使用户能够使用相同的账户和凭据在所有这些域上登录。WebAuthn 标准会对这些场景构成挑战,因为 Passkey 只能绑定到一个域(Relying Party ID),例如 www.kayak.com。
为了克服这一挑战,您可以在所有其他域上使用来自 www.kayak.com 源的 iframe。因此,您在 www.kayak.us 和 www.kayak.de 上嵌入一个源为 www.kayak.com 的 iframe(跨源 iframe)。否则,由于 Passkey 的钓鱼抵抗性,您将无法在这些其他域上使用绑定到“www.kayak.com”的 Passkey。
顺便提一下:也可以使用 WebAuthn 的新功能 Related Origin Requests (RoR) 作为替代方案。该功能允许“相关源”在没有 iframe 的情况下访问 Passkey,但目前并非所有浏览器都支持。
对于无缝的支付流程,在跨源 iframe 中使用 Passkey 也扮演着重要角色。考虑以下场景:一位顾客想在商家(merchant)网站(例如 www.amazon.com)上购买新鞋。该商家网站允许顾客通过银行账户(例如在 www.revolut.com)支付,因此需要用户登录银行网站(这是一个简化流程)。用户使用绑定到银行 Relying Party ID(例如“revolut.com”)的 Passkey 登录银行网站。
为了避免在结账过程中将用户从商家网站(www.amazon.com)重定向到银行网站(www.revolut.com)并在那里登录银行账户,可以使用跨源 iframe。这样,用户停留在 www.amazon.com 上,并在跨源 iframe 中使用他们为 www.revolut.com 创建的 Passkey 进行身份验证。
因此,通过跨源 iframe 在支付流程中集成 Passkey,可以确保消费者、商家和银行之间的交易安全且流程顺畅:
消费者 | 商家 | 银行 |
---|---|---|
|
|
|
在支付和 Passkey 的背景下,我们还建议您查看我们关于安全支付确认(SPC)和 Passkey 动态链接的博文。也请务必查看下文关于原生应用中第三方上下文的限制。
此外,要更深入地了解使用 Passkey 的跨源支付流程,请参阅我们的支付提供商 Passkey:如何构建第三方 SDK。
总的来说,在 iframe 中集成 Passkey 提供了几个好处,主要是通过改善用户体验和安全性。以下是这些优势的详细分析:
增强的用户体验
提高安全性
在 iframe 中实现 Passkey 涉及一些关键步骤,以确保安全性和功能性。我们为开发者提供了一份详细的指南。另请参阅 https://cross-origin-iframe.vercel.app/ 上的实现示例。
HTTP Permissions-Policy
标头有助于允许或拒绝对文档或 iframe 元素中某些浏览器功能的使用。要在 iframe 中启用 Passkey 登录,您必须设置
publickey-credentials-get
和
publickey-credentials-create
权限策略。这些策略允许嵌入的内容调用必要的 WebAuthn
API 方法来进行身份验证(navigator.credentials.get({publicKey})
)和创建 Passkey(navigator.credentials.create({publicKey})
)。
<iframe src="https://passkeys.eu" allow="publickey-credentials-get; publickey-credentials-create"></iframe>
HTTP Permissions Policy
以前称为 Feature Policy
。在 Feature Policy
下,您可以通过将源添加到标头源列表或在 iframe 标签中包含 allow
属性来向跨源 iframe 授予功能。使用 Permissions Policy
时,将跨源框架添加到源列表要求该源的 iframe 标签必须包含 allow
属性。如果响应缺少
Permissions Policy
标头,则源列表默认为 *
(所有源)。在 iframe 中包含 allow
属性会授予对该功能的访问权限。
为确保未在源列表中指定的跨源 iframe 即使存在 allow
属性也无法访问该功能,开发者可以在响应中明确设置 Permissions Policy
标头。
在 Chrome 88+ 中,仍然可以使用 Feature Policy
,但它作为 Permissions Policy
的别名。除了语法差异外,逻辑保持不变。当同时使用 Permissions Policy
和 Feature Policy
标头时,Permissions Policy
标头具有优先权,并将覆盖 Feature Policy
标头设置的值。另请参阅
Chrome 团队的这篇博文以获取更多实现细节。
确保来自 iframe 源 URL 的 HTTP 响应标头包含相关的
Permissions-Policy
。这对于跨源支持至关重要。
Permissions-Policy: publickey-credentials-get=*, publickey-credentials-create=*
为了进行更精细的控制,您可以指定允许嵌入 iframe 内容的特定源。
Permissions-Policy: publickey-credentials-get=("https://passkeys.eu"), publickey-credentials-create=("https://passkeys.eu")
确保 iframe 内容需要用户操作才能触发 Passkey 身份验证。这可以通过在 iframe 内使用点击或表单提交的事件监听器来完成。这个过程也称为瞬时激活 (transient activation)。
document.getElementById("loginPasskeyButton").addEventListener("click", async () => { try { const publicKeyCredentialRequestOptions = { /* Configuration options */ }; const credential = await navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions, }); // Handle the created credential } catch (err) { console.error("Error authenticating via passkey:", err); } });
在此背景下,另请参阅我们关于 Safari 用户手势要求的博文。
下面是一个托管在
https://cross-origin-iframe.vercel.com 上的
index.html
文件的完整代码片段示例,它通过 https://passkeys.eu
使用跨源 iframe 实现 Passkey。
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="Permissions-Policy" content="publickey-credentials-get=*; publickey-credentials-create=*" /> <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; img-src 'self'; frame-src https://passkeys.eu;" /> <title>Cross-Origin iframe with Passkeys Demo</title> <style> body { font-family: Arial, sans-serif; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100vh; margin: 0; } h1 { width: 100%; text-align: center; } .iframe-container { width: 80%; max-width: 800px; height: 80%; max-height: 600px; border: 1px solid #ccc; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); margin-top: 20px; } iframe { width: 100%; height: 100%; border: none; } @media (max-width: 768px) { h1 { width: 95%; } .iframe-container { width: 95%; } } </style> </head> <body> <h1>Cross-Origin iframe with Passkeys Demo</h1> <div class="iframe-container"> <iframe src="https://passkeys.eu" allow="publickey-credentials-create; publickey-credentials-get" ></iframe> </div> </body> </html>
在 iframe 中实现 Passkey 可能会遇到一系列挑战,开发者需要解决这些挑战以确保流畅和安全的用户体验。以下是常见挑战及其解决方法的详细介绍。
问题: 错误配置权限策略可能导致 iframe 无法访问 WebAuthn API。
“NotAllowedError - The 'publickey-credentials-create' feature is not enabled in this document. Permissions Policy may be used to delegate Web Authentication capabilities to cross-origin child frames.”
如果您没有正确添加权限策略,浏览器会抛出以下错误:
解决方法:
allow
属性和 HTTP 标头已正确设置。仔细检查 publickey-credentials-get
和
publickey-credentials-create
权限是否已包含在 iframe 元素和服务器的 HTTP 响应标头中。<meta/>
标头来定义权限策略,而不是在您的 Web 服务器中设置标头。Permissions-Policy
被称为
Feature-Policy
。Feature-Policy
的单个元素用逗号分隔,而不是分号(这是
Permissions-Policy
的标准)。iframe 的 Permissions-Policy
仍然遵循 Feature-Policy
的语法,因此使用逗号。但 sandbox / allow
属性仍然用分号分隔(见上面的代码片段)。提示: 为了正确测试您的 Permission-Policy
标头是否设置正确,我们建议您打开浏览器的开发者工具,进入 Application
选项卡(此处以 Chrome 开发者工具为例),转到 Frames
并搜索 iframe 的源(此处为 passkeys.eu/)。如果 Permissions-Policy
设置正确,publickey-credential-create
和 publickey-credential-get
应该会列在 Allowed
Features 中:
问题: 跨源 iframe 的 Passkey 创建或 Passkey 登录不起作用,并且您在浏览器控制台中看到以下错误。
"NotAllowedError - The origin of the document is not the same as its ancestors."
当使用 Safari 浏览器并尝试从 iframe 内创建 Passkey 时,会出现此错误,因为 Safari 不支持跨源 iframe 的 Passkey 创建(见上文)。
解决方法: 在这里,您几乎无能为力,因为 Safari(目前)尚不支持从跨源 iframe 内创建 Passkey。
Blocked a frame with origin "https://passkeys.eu" from accessing a frame with origin "https://cross-origin-iframe.vercel.app". Protocols, domains, and ports must match.
这个错误与 Passkey 没有直接关系,更多是关于 Safari 中跨源 iframe 的普遍问题。作为 Safari / WebKit 阻止第三方 Cookie 或在第三方上下文中访问 LocalStorage 举措的一部分,部分 JavaScript 逻辑可能会被破坏。
解决方法: 在这里,您需要确保不在 iframe 内使用第三方 Cookie,因为这会导致错误。
问题: 当不同浏览器对 WebAuthn、iframe 权限和安全属性的支持程度不同时,会出现 iframe 浏览器兼容性问题,导致行为不一致。
解决方法: 为了缓解这些 iframe 浏览器兼容性问题,请在多个浏览器上测试实现,以确保兼容性并识别任何特定于浏览器的问题。
步骤:
问题: 在原生应用中使用需要 Passkey 的 iframe 时,必须对第一方和第三方上下文做出关键区分:
在嵌入式 WebView (EWV)(例如 iOS 上的 WKWebView 或 Android 上的 WebView)中,调用应用对 Web 会话有广泛的控制权(例如,拦截请求)。这种设置通常仅在 Passkey 的域(Relying Party ID)与应用的域(第一方)匹配时才支持 Passkey。然而,在第三方场景中——比如支付提供商的跨源流程——嵌入式 WebView 通常无法访问所需的 Passkey 凭据,因为商家应用和支付提供商的服务是不同的源。Passkey 所需的“绑定”(域、凭据和源之间)在嵌入式上下文中将不匹配。
这一限制导致许多应用采用系统 WebView 方法(例如 iOS 上的 ASWebAuthenticationSession 或 Android 上的 Custom Tabs)。系统 WebView 将第三方网站(例如支付提供商)隔离在一个安全的、类似浏览器的环境中,该环境正确地允许跨源 Passkey——前提是浏览器本身支持它。然而,请记住,Safari 现有的 iframe 限制也适用于 ASWebAuthenticationSession,因此如果 Safari 不允许在第三方 iframe 中进行某些 Passkey 操作,那么在系统 WebView 中也是如此。目前没有“原生”修复方案;对于复杂流程——例如涉及外部支付提供商的结账——的最佳实践是打开一个系统 WebView 而不是嵌入式 WebView。
解决方法: 对于支付提供商(以及其他依赖跨域 Passkey 的第三方),请仔细规划集成,以确保用户从嵌入式 WebView 转到系统 WebView。虽然这比纯嵌入式流程的体验要差一些,但这通常是保证 Passkey 功能与第三方服务正常工作的唯一方法。
有关在原生应用和 WebView 中处理第三方 Passkey 的更多详细信息,请查看支付提供商 Passkey:第三方 Passkey 支付 SDK。
虽然上面讨论的主题适用于各种场景,但它们对支付提供商尤其重要,因为在这些场景中,多域流程(例如,商家网站和支付网关)必须在跨源 iframe 内嵌入用户认证。在这些设置中:
pay.provider.com
)上处理 Passkey 注册或登录,即使它们被嵌入到商家网站中。为了应对这些挑战并构建类似于 Apple Pay 的安全、无缝的体验,支付提供商通常采用混合方法——将基于 iframe 的集成与针对 Safari(或旧版浏览器)的重定向回退相结合。在某些情况下,如果嵌入式 WebView 完全不允许 Passkey,系统浏览器流程(例如 iOS 上的 ASWebAuthenticationSession)就成为强制性选择。
要深入了解这些特定于支付的场景——包括 iframe 与重定向的比较、原生应用的注意事项以及提高 Passkey 采用率的最佳实践,请参阅我们的专题文章:
60-page Enterprise Passkey Whitepaper:
Learn how leaders get +80% passkey adoption. Trusted by Rakuten, Klarna & Oracle
特别是:
Permissions-Policy
设置。这份补充指南为保护交易、克服 Safari 的跨源限制以及在第三方上下文中优化 Passkey 使用提供了深入的策略。通过将本文中的技术步骤与那些专注于支付的方法相结合,您可以直接在 iframe 内提供无摩擦、抗钓鱼的结账流程,从而为在线支付解锁更高水平的安全性和用户体验。
在 iframe 中集成 Passkey 通过提高安全性和用户体验,显著增强了用户认证。这使得无缝身份验证成为可能,无需重定向或弹窗,确保了在不同部分和网站之间的一致用户体验。
现实世界的实现,例如 Shopify 在其登录组件中集成 Passkey 的实践,展示了这种方法的实际好处和灵活性。
Enjoyed this read?
🤝 Join our Passkeys Community
Share passkeys implementation tips and get support to free the world from passwords.
🚀 Subscribe to Substack
Get the latest news, strategies, and insights about passkeys sent straight to your inbox.
Related Articles
Table of Contents