使用 WebOTP API 在跨源 iframe 中填充动态密码表单

WebOTP API 现在可以从 iframe 中接收动态密码。

短信动态密码(动态密码)通常用于验证电话号码,例如用作身份验证的第二个验证步骤,或用于在网络上验证付款。但是,如果在浏览器和短信应用之间切换,为了复制粘贴或手动输入动态密码,很容易出错,还会给用户体验带来不便。

借助 WebOTP API,网站能够以程序化方式从短信中获取动态密码,然后用户只需点按一下表单即可自动输入该密码,而无需切换应用。短信是特殊格式并绑定到源的,因此也能降低钓鱼式攻击网站窃取动态密码的机会。

WebOTP 尚不支持的一种使用情形是定位到 iframe 内的来源。这通常用于付款确认,尤其是使用 3D Secure 时。WebOTP API 采用支持跨源 iframe 的常用格式,现在提供从 Chrome 91 开始绑定到嵌套源的动态密码。

WebOTP API 的工作原理

WebOTP API 本身非常简单:

…
  const otp = await navigator.credentials.get({
    otp: { transport:['sms'] }
  });
…

短信必须采用与源站绑定的一次性验证码的格式。

Your OTP is: 123456.

@web-otp.glitch.me #12345

请注意,最后一行包含要绑定到的来源,后跟 @,后跟动态密码,再后跟 #

收到短信时,系统会弹出一个信息栏,提示用户验证其电话号码。用户点击 Verify 按钮后,浏览器会自动将动态密码转发到网站并解析 navigator.credentials.get()。然后,网站就可以提取动态密码并完成验证流程。

请参阅使用 WebOTP API 在网络上验证电话号码,了解使用 WebOTP 的基础知识。

跨源 iframe 用例

在付款场景中,在跨源 iframe 内的表单中输入动态密码很常见。某些信用卡发卡机构要求执行额外的验证步骤来检查付款人的真实性。这称为 3D 安全,该表单通常位于付款流程的同一网页上的 iframe 内。

例如:

  • 某用户访问了 shop.example,并用信用卡购买了一双鞋。
  • 输入信用卡号后,集成的付款服务机构会在 iframe 中显示 bank.example 的表单,要求用户验证其电话号码以便快速结账。
  • bank.example 会向用户发送包含动态密码的短信,以便用户输入该密码以验证身份。

如何通过跨源 iframe 使用 WebOTP API

如需在跨源 iframe 中使用 WebOTP API,您需要执行以下两项操作:

  • 在短信中同时标注顶部框架来源和 iframe 来源。
  • 配置权限政策,以允许跨源 iframe 直接从用户接收动态密码。
iframe 中的 WebOTP API 的实际运用。

您可以访问 https://web-otp-iframe-demo.stackblitz.io 自行试用该演示。

为短信的绑定源添加注解

从 iframe 中调用 WebOTP API 时,短信必须包含顶部帧来源,后跟 @,后跟动态密码,后跟 #,接着是 iframe 来源,且后跟 @

@shop.example #123456 @bank.exmple

配置权限政策

如需在跨源 iframe 中使用 WebOTP,嵌入者必须通过 OTP 凭据权限政策授予对此 API 的访问权限,以避免意外行为。一般来说,可以通过两种方法实现这一目标:

  • 通过 HTTP 标头:
Permissions-Policy: otp-credentials=(self "https://bank.example")
  • 通过 iframe allow 属性:
<iframe src="https://bank.example/…" allow="otp-credentials"></iframe>

查看有关如何指定权限政策的更多示例

注意事项

嵌套级别

目前,Chrome 仅支持来自祖先链中不超过一个唯一来源的跨源 iframe 的 WebOTP API 调用。在以下情况下:

  • a.com -> b.com
  • a.com -> b.com -> b.com
  • a.com -> a.com -> b.com
  • a.com -> b.com -> c.com

我们支持在 b.com 中使用 WebOTP,但在 c.com 中使用 WebOTP 不受支持。

请注意,由于需求不足且用户体验复杂,以下场景也不受支持。

  • a.com -> b.com -> a.com(调用 WebOTP API)

互操作性

虽然 Chromium 以外的浏览器引擎不会实现 WebOTP API,但 Safari 与其 input[autocomplete="one-time-code"] 支持共用相同的短信格式。在 Safari 中,一旦收到包含与来源绑定的一次性代码格式的短信以及匹配的来源,键盘就会建议在输入字段中输入动态密码。

从 2021 年 4 月开始,Safari 支持使用 % 以独特短信格式的 iframe。不过,随着规范讨论结束,改用 @,我们希望受支持的短信格式的实现能够趋于一致。

反馈

您的反馈对于改进 WebOTP API 至关重要,因此请继续试用并告诉我们您的想法。

资源

照片由 rupixen.com 提供,由 Unsplash 提供