使用 WebOTP 获得更佳的双因素身份验证体验
双因素身份验证 (2FA) 是提升应用程序用户帐户安全性的有效方法。它有助于防止常见的密码安全问题,例如用户选择容易被猜到的密码或在多个网站上重复使用同一密码。实现双因素身份验证的方法有很多种,包括短信验证、使用身份验证器应用程序和 WebAuthn。
短信验证是目前应用最广泛的验证方式,而且不会过时,因此作为开发者,我们有责任尽最大努力为用户打造最佳的短信双因素认证体验。WebOTP API 是我们可以帮助用户减少登录过程中的摩擦,甚至提供一定程度的防钓鱼保护的一种途径。
什么是 WebOTP API?
WebOTP API是凭证管理 API的扩展。凭证管理 API 最初允许我们在浏览器的密码管理器中存储和访问凭证,但现在已涵盖WebAuthn和双因素身份验证。WebOTP API 允许我们请求用户授权,从收到的短信中读取双因素身份验证代码。
当您集成 WebOTP API 后,登录流程的第二步就可以从繁琐的从短信中读取并复制数字,简化为只需按一下按钮即可。相信您也会认同,这是一项巨大的改进。
它是如何运作的?
要实现 WebOTP,您需要做两件事:
- 更新您发送的 WebOTP 格式消息
- 在登录页面添加一些 JavaScript 代码,以请求读取消息的权限。
短信
为了让 WebOTP API 将消息识别为传入的双因素身份验证 (2FA) 代码,您需要在发送的消息末尾添加一行。该行必须包含一个@符号,后跟用户将要登录的网站域名,然后是一个空格,再是一个#符号,最后是验证码本身。如果您的用户正在登录某个网站example.com,并且您发送给他们的验证码是某个特定网站123456,则消息应如下所示:
您登录应用程序的代码是 123456
@example.com #123456
域名将消息与用户应该登录的网站关联起来。这有助于防范网络钓鱼。如果用户登录的网站域名与消息中的域名不匹配,WebOTP 就无法通过短信请求验证码。当然,这无法阻止用户复制短信中的验证码,但如果用户习惯了这种行为,可能会让他们有所顾虑。
JavaScript
一旦你的消息格式设置正确,你需要第二因素页面上的一些 JavaScript 代码来触发 WebOTP API,请求用户访问消息的权限并收集代码。
这段代码的最简版本如下所示:
if ('OTPCredential' in window) {
navigator.credentials.get({
otp: {
transport: ['sms']
}
}).then((otp) => {
submitOTP(otp.code);
});
}
我们要求navigator.credentials对象从短信传输中获取一次性密码 (OTP)。如果浏览器检测到包含正确域名和验证码的短信,则会提示用户授予访问权限。如果用户批准,则 Promise 会解析为一个otp包含特定code属性的对象。然后,您可以将该验证码提交到表单,完成用户的登录过程。
更完整的代码版本(可以处理诸如查找输入框和表单、表单提交后取消请求以及请求成功后提交表单等操作)如下所示:
if ('OTPCredential' in window) {
window.addEventListener('DOMContentLoaded', e => {
const input = document.querySelector('input[autocomplete="one-time-code"]');
if (!input) return;
const ac = new AbortController();
const form = input.closest('form');
if (form) {
form.addEventListener('submit', e => ac.abort());
}
navigator.credentials.get({
otp: { transport:['sms'] },
signal: ac.signal
}).then(otp => {
input.value = otp.code;
if (form) {
form.submit();
}
}).catch(err => {
console.error(err);
});
});
}
这种方法适用于很多网站,但是复制粘贴代码并不是分享代码的最佳方式,所以我想到了一种更简单的方法。
使用 Web 组件的声明式 WebOTP
在 Safari 浏览器中,您可以通过<input>向 OTP 代码元素添加一个属性来实现与 WebOTP API 类似的功能。设置此属性后,autocomplete="one-time-code"Safari 会通过自动完成功能提供短信中的验证码。
受此启发,我希望 WebOTP 的使用也能同样简单。因此,我发布了一个 Web 组件,即 ` <component>`<web-otp-input>组件,它负责处理整个流程。您可以在 GitHub 上查看所有代码及其使用方法。例如,您可以将该组件作为 ES 模块添加到您的页面中:
<script type="module" src="https://unpkg.com/@philnash/web-otp-input"></script>
或者通过 npm 将其安装到您的项目中:
npm install @philnash/web-otp-input
并将其导入到您的应用程序中:
import { WebOTPInput } from "@philnash/web-otp-input";
然后,你可以像这样将它包裹<web-otp-input>在现有的<input>元素周围:<form>
<form action="/verification" method="POST">
<div>
<label for="otp">Enter your code:</label>
<web-otp-input>
<input type="text" autocomplete="one-time-code" inputmode="numeric" id="otp" name="otp" />
</web-otp-input>
</div>
<button type="submit">Submit</button>
</form>
这样,任何使用支持 WebOTP 的浏览器的用户都会自动体验 WebOTP,而无需编写任何额外的 JavaScript 代码。
WebOTP:更佳体验
WebOTP API 让短信双因素认证体验更佳。对于支持该 API 的浏览器,用户可以轻松输入作为第二因素发送的验证码。
甚至在某些情况下,它也能用于桌面浏览器。例如,如果用户在桌面和安卓设备上都安装了 Chrome 浏览器,并且都登录了 Google 帐户,那么在桌面设备上登录后,移动设备上会收到一条通知,询问是否允许将验证码发送到桌面。在移动设备上批准该通知后,验证码就会传输到桌面浏览器。您甚至无需编写额外的代码来处理这种情况,只需要本文中提供的 JavaScript 代码即可。
有关 WebOTP 的更多信息,请查看以下文章:
如果您正在构建双因素身份验证或手机验证,请考虑同时实现 WebOTP API,以简化用户的操作流程。
文章来源:https://dev.to/philnash/better-two-factor-authentication-experiences-with-webotp-1ncm
