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

WebOTP API 现在可以从 iframe 中接收 OTP。

短信动态密码(一次性密码)通常用于验证电话号码,例如作为身份验证的第二步,或用于验证网络上的付款。 不过,在浏览器和短信应用之间切换以复制粘贴或手动输入 OTP 很容易出错,并会增加用户体验的摩擦。

WebOTP API 使网站能够以程序化方式从短信中获取一次性密码,并只需用户点按一下即可自动将其输入到表单中,而无需切换应用。短信采用特殊格式,并与来源绑定,因此还可以降低钓鱼网站窃取 OTP 的几率。

WebOTP 尚未支持的一个用例是定位 iframe 内的来源。此参数通常用于付款确认,尤其是在使用 3D Secure 时。采用通用格式来支持跨源 iframe 后,WebOTP API 现在可以提供与嵌套来源绑定的 OTP(从 Chrome 91 开始)。

WebOTP API 的工作原理

WebOTP API 本身非常简单:


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

短信必须采用源绑定的一次性代码格式

Your OTP is: 123456.

@web-otp.glitch.me #12345

请注意,最后一行包含要绑定的来源,前面带有 @,后面是 OTP,前面带有 #

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

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

跨源 iframe 应用场景

在跨源 iframe 中的表单内输入一次性密码在付款场景中很常见。部分信用卡发卡机构要求进行额外的验证步骤,以检查付款人的真实性。这称为 3D Secure,该表单通常在同一页面上的 iframe 中公开,就像它是付款流程的一部分一样。

例如:

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

如何从跨源 iframe 使用 WebOTP API

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

  • 在短信文本消息中同时注释顶级框架来源和 iframe 来源。
  • 配置权限政策,以允许跨源 iframe 直接从用户处接收 OTP。
iframe 中的 WebOTP API 实际应用。

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

为短信添加了绑定来源注释

当从 iframe 内调用 WebOTP API 时,短信文本消息必须包含以下内容:以 @ 开头的顶级框架来源、以 # 开头的 OTP 以及以 @ 开头的 iframe 来源。

@shop.example #123456 @bank.exmple

配置权限政策

如需在跨源 iframe 中使用 WebOTP,嵌入者必须通过 otp-credentials 权限政策授予对该 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 中使用。

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

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

互操作性

虽然 Chromium 以外的浏览器引擎未实现 WebOTP API,但 Safari 与其 input[autocomplete="one-time-code"] 支持功能共享相同的 SMS 格式。在 Safari 中,当收到包含与来源绑定的格式的一次性验证码的短信时,如果来源匹配,键盘会建议在输入字段中输入 OTP。

自 2021 年 4 月起,Safari 支持使用 %独特短信格式的 iframe。不过,由于规范讨论最终决定使用 @,我们希望受支持的短信格式的实现能够趋于一致。

反馈

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

资源

照片提供者:rupixen.com;来源:Unsplash