深入了解 WebAuthn 即时中介。了解它如何创建单一登录按钮、避免令人困惑的二维码并构建更智能的登录流程。
Vincent
Created: August 8, 2025
Updated: August 13, 2025
See the original blog version in English here.
60-page Enterprise Passkey Whitepaper:
Learn how leaders get +80% passkey adoption. Trusted by Rakuten, Klarna & Oracle
向 Passkey 的过渡正在造成一个“Passkey 悖论”:一些用户已经拥有 Passkey,但许多人仍在使用传统的密码。这导致登录界面变得混乱,出现了多个按钮:“使用密码登录”、“使用 Google 登录”和“使用 Passkey 登录”。这种碎片化带来了不便。用户可能会在新设备上点击“使用 Passkey 登录”,结果却看到一个令人困惑的二维码提示,因为他们的 Passkey 在本地不可用。核心问题在于,网站在启动认证流程前,无法了解用户的具体情况。
一种解决方案是采用“标识符优先”的策略,以此判断用户的最佳登录方式。另一种潜在的解决方案是打造一个智能的单一“登录”按钮,为每位用户安排最顺畅的流程。如果设备上有可用的 Passkey,它应该直接提示用户使用;如果没有,则应优雅地回退到其他方法。
最近发布的一项新的 WebAuthn 功能有望实现这一点:即时中介(mediation: 'immediate'
)。通过在 WebAuthn
API 调用中设置此属性,开发者可以构建一个智能、统一的登录体验,从而解决 Passkey 悖论。本文将从开发者的角度深入分析
mediation: 'immediate'
,探讨它是什么、如何工作以及如何实现它。
要理解即时中介,首先了解其他选项会很有帮助。WebAuthn 中的用户中介是指浏览器管理你的网站(即信赖方)与用户认证器(例如 Face ID、YubiKey)之间交互的方式。
这是经典的、显式的 WebAuthn 流程。当信赖方 (Relying Party) 调用
navigator.credentials.get()
而未指定 mediation
偏好时,浏览器总是会弹出一个模态对话框。这个对话框会覆盖页面内容,强制要求用户立即关注,并暂停与网站的所有其他交互。
mediation: 'conditional'
#该模式的引入是为了帮助用户过渡到 Passkey,它更为巧妙。使用
mediation: 'conditional'
时,WebAuthn 请求会附加到一个带有 autocomplete="webauthn"
属性的输入字段(例如用户名)。当用户点击该字段时,浏览器的自动填充界面会建议任何可用的 Passkey。
mediation: 'immediate'
是解决“单一登录按钮”问题的方案。它为网站提供了一种可靠的方式,在显示任何 UI 之前检查 Passkey 的可用性。
即时中介并非通过模态框_告诉_用户使用 Passkey 进行认证,而是_询问_浏览器:“此设备上现在是否有立即可用的 Passkey?”
关键在于,此查询只检查_本地可用_的凭据(例如,设备内置的认证器如 Windows Hello 或通过密码管理器同步的 Passkey)。它旨在避免触发跨设备的二维码流程,因为这是一个常见的痛点。
此功能的强大之处在于其清晰的二元结果。navigator.credentials.get()
返回的 promise 要么成功,要么失败,为开发者提供了明确的信号。
PublicKeyCredential
对象。navigator.credentials.get()
的 promise 会_立即_以一个名为 NotAllowedError
的 DOMException
拒绝。NotAllowedError
不是一个 bug,它更像一个特性。它是一个可靠、即时的信号,告诉网站应该继续使用后备认证方法。这使得开发者可以使用一个简单的
try...catch
代码块:try
代码块尝试无缝的 Passkey 流程,而 catch
代码块则监听
NotAllowedError
以渲染传统的登录表单。它通过创建一个能智能适应用户环境的单一入口点,优雅地解决了单一登录按钮的问题。
选择正确的中介模式是一项关键的用户体验决策。下表提供了并排比较。
特性 / 行为 | 模态(默认) | 条件式 UI (conditional ) | 即时 (immediate ) |
---|---|---|---|
API 调用 | navigator.credentials.get() | navigator.credentials.get({ mediation: 'conditional' }) | navigator.credentials.get({ mediation: 'immediate' }) |
触发方式 | 明确的用户操作(如点击按钮) | 页面加载时触发;输入框聚焦时显示 UI | 明确的用户操作(如点击按钮) |
UI 呈现 | 总是立即显示模态对话框。 | 显示非模态的自动填充式 UI。 | 仅当找到本地凭据时,才显示模态对话框。 |
无本地凭据时的行为 | 显示跨设备流程的 UI(如二维码)。 | Promise 保持待定,永不解析,不抛出错误。 | Promise 立即以 NotAllowedError 拒绝。 |
网站获知的信息 | 在用户完成流程前一无所知。 | 如果用户不交互则一无所知。隐私性最高。 | 获知一位信息:是否存在本地凭据。 |
主要使用场景 | 专用的“使用 Passkey 登录”按钮。显式双因素认证。 | 统一的登录/注册表单。渐进式增强密码表单。 | 为混合用户群设计的单一主“登录”按钮。 |
开发者操作 | 处理成功或用户取消操作。 | 处理成功。没有可供操作的失败信号。 | 处理成功或 NotAllowedError 以触发后备 UI。 |
以下是实现 mediation: 'immediate'
的实用分步指南。
由于 mediation: 'immediate'
是一项新功能,因此稳健的特性检测至关重要。
// 特性检测对于渐进式增强至关重要。 let immediateMediationAvailable = false; if (window.PublicKeyCredential && PublicKeyCredential.getClientCapabilities) { try { const capabilities = await PublicKeyCredential.getClientCapabilities(); // 'immediateGet' 能力标志着浏览器的支持。 immediateMediationAvailable = capabilities.immediateGet === true; } catch (e) { console.error("获取客户端能力时出错:", e); } }
navigator.credentials.get()
调用#此调用必须由用户手势(如点击按钮)触发。
// 此函数应作为主“登录”按钮的事件处理程序。 async function handleSignInClick() { if (!immediateMediationAvailable) { // 如果不支持该功能,则回退到显示旧版登录表单。 showLegacyLoginForm(); return; } try { // 每次尝试都从服务器获取一个新的随机质询。 const challenge = await fetchChallengeFromServer(); const publicKeyCredentialRequestOptions = { challenge: challenge, // 服务器提供的质询,为 Uint8Array 格式 rpId: "example.com", // 为保护用户隐私,allowCredentials 列表必须为空 // 以进行即时中介。 allowCredentials: [], }; const credential = await navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions, // 这是启用即时中介流程的关键。 mediation: "immediate", }); // 如果 promise 解析成功,将凭据发送到服务器进行验证。 await verifyCredentialOnServer(credential); } catch (error) { // catch 代码块是控制流的关键部分。 handleAuthError(error); } }
NotAllowedError
以实现优雅回退#catch
代码块是实现单一登录按钮“智能”的地方。
// 处理 NotAllowedError 是后备机制的关键。 function handleAuthError(error) { // 检查 DOMException 的 'name' 属性。 if (error.name === "NotAllowedError") { // 这是预期的信号,用于显示传统登录表单。 console.log("未找到本地 Passkey。正在显示旧版登录表单。"); showLegacyLoginForm(); } else { // 这里处理其他潜在错误,例如用户关闭了提示框。 console.error("认证错误:", error); } }
为了获得最无缝的体验,你可以通过添加
password: true
,让浏览器在同一次请求中同时搜索 Passkey 和已保存的密码。
// 结合 Passkey 和密码,打造真正统一的登录体验。 const credential = await navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions, password: true, // 请求浏览器包含已保存的密码。 mediation: "immediate", }); // 返回的 'credential' 对象将是 PublicKeyCredential // 或 PasswordCredential。你的服务器端逻辑必须能处理这两种情况。
conditional
请求(通常在页面加载时启动)可能会阻塞一个新的 immediate
请求。可以考虑使用
AbortController
在启动新请求前取消任何待处理的请求。allowCredentials
限制: allowCredentials
数组必须为空。提供凭据 ID 会导致调用失败。这是一项关键的隐私保护措施,以防止网站检查特定的已知用户。mediation: 'immediate'
的设计清晰地考虑了其在安全和隐私方面的权衡。
核心的权衡是一种“一位信息泄露”。通过计时 promise 的解析,信赖方 (Relying Party) 可以推断出一位信息:promise 是立即被拒绝(无本地凭据),还是有所延迟(因找到本地凭据而显示了 UI 提示)。这种信息泄露的目的是为了实现更好的用户体验。
设计者预见到了滥用的可能性(例如用户追踪),并内置了几个不可协商的保障措施:
allowCredentials
列表: allowCredentials
数组必须为空。这可以防止网站利用此功能来检查某个_特定_的已知用户是否正在访问。iframe
)中被禁止,以防止跨站追踪。这些缓解措施确保了 WebAuthn 的核心安全保障不受影响。认证仪式本身没有改变,并且仍然是抗网络钓鱼的。
mediation: 'immediate'
是
WebAuthn Level 3 规范中的一项高级功能,其推广仍在进行中。截至 2025 年中期,采用渐进式增强策略至关重要。
浏览器 | 状态 | 说明与来源 |
---|---|---|
Chrome | 开发者试用版 | 可通过 experimental-web-platform-features 标志启用。 追踪问题。 |
Edge | 开发中(预期) | 作为 Chromium 浏览器,支持情况应会跟随 Chrome。 |
Safari (WebKit) | 考虑中 | WebKit 标准立场。尚无公开承诺。 |
Firefox (Gecko) | 考虑中 | Mozilla 标准立场。尚无公开承诺。 |
虽然 mediation: 'immediate'
为实现更智能的登录按钮提供了一个出色的底层工具,但重要的是要将其与更广泛的“Passkey 智能 (Passkey Intelligence)”解决方案(例如 Corbado 提供的方案)区分开来。两者都旨在解决 Passkey 悖论并提高采用率,但实现方式不同。
特性 | mediation: 'immediate' | Passkey 智能(例如 Corbado) |
---|---|---|
工作原理 | 一个浏览器原生的 API 调用,用于检查当前设备上本地可用的 Passkey。 | 一个后端服务,用于收集和分析跨会话的用户设备、认证器和登录历史数据。 |
提供的信号 | 一个简单的二元信号:本地 Passkey 要么存在(UI 提示 ),要么不存在(NotAllowedError )。 | 丰富的上下文洞察,例如,“该用户刚刚在一台他们常用且支持 Passkey 的设备上用密码登录了。” |
主要优势 | 非常快速的原生检查,网络开销极小。 | 通用性强,不依赖于浏览器/操作系统对新 WebAuthn 功能的支持。更深入的洞察可提供更定制化的用户体验。 |
主要依赖 | 需要最新的浏览器和操作系统支持,目前尚未普及。 | 与后端服务的集成。 |
Passkey 智能通过长期收集和评估数据更进一步。这使得更复杂和及时的用户干预成为可能。例如,一个 Passkey 智能后端可以检测到:
这种数据驱动的方法不依赖于浏览器对 mediation: 'immediate'
的支持,这意味着它现在就可以为你的所有用户提供更智能的登录流程。
两全其美
最终,这两种方法并非相互排斥,而是互补的。理想的解决方案将它们结合起来:
mediation: 'immediate'
作为其信号之一,进行快速的初始检查。通过将 mediation: 'immediate'
的原生速度与
Passkey 智能后端的深度洞察相结合,你可以提供最无缝、自适应且高效的登录体验,温和地引导每位用户走向无密码的未来。
即时中介是对登录体验的一次巨大升级。它提供了所需的智能,以消除用户在向 Passkey 过渡期间常见的痛点和困惑。
immediate
中介减轻了用户的认知负荷。他们不再需要记住自己设置了哪种认证方法,也无需从一堆混乱的选项中选择。登录过程变得更简单、更直观。mediation: 'immediate'
只查找本地凭据,它完全避免了这种令人困惑的状态。应用程序不会让用户中断流程,而是会收到一个明确的信号(NotAllowedError
),从而优雅地回退到另一种方法,带来更顺畅的体验。即时中介是一项新的 WebAuthn 功能,它解决了 Passkey 过渡时期碎片化的登录体验。它能够创建一个单一、智能的“登录”按钮,该按钮能适应用户的具体情况,从而消除困惑和不便。虽然它引入了经过计算的隐私权衡,但也包含了强大的保障措施来降低风险,而不会损害 WebAuthn 的核心安全性。
对于开发者来说,前进的道路是渐进式增强。构建一个坚实的基线体验,并在支持的浏览器上层叠
immediate
中介。采用此功能是一项战略性举措,可以加速
Passkey 的采用,增强安全性,降低运营成本并提高转化率。
实现这些高级认证流程可能很复杂。Corbado 的企业级 Passkey 平台将这种复杂性抽象化。我们的基础设施负责处理最优的流程编排——包括条件中介和
immediate
中介,让你的团队能够自信地部署顶尖的、无摩擦的认证体验。
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