WebOTP API

可用性有限

此特性不是基線特性,因為它在一些最廣泛使用的瀏覽器中不起作用。

實驗性: 這是一項實驗性技術
在生產中使用此技術之前,請仔細檢查瀏覽器相容性表格

安全上下文: 此功能僅在安全上下文(HTTPS)中可用,且支援此功能的瀏覽器數量有限。

WebOTP API 提供了一種簡化的使用者體驗,讓 Web 應用程式可以在使用者使用手機號碼作為登入因素時,驗證手機號碼是否屬於使用者。WebOTP 是 Credential Management API 的一個擴充套件。

驗證透過一個兩步過程完成。

  1. 應用客戶端請求一個一次性密碼(OTP),該 OTP 來自應用伺服器傳送的一個特殊格式的簡訊。
  2. 使用 JavaScript 將 OTP 輸入到應用客戶端的驗證表單中,然後將其提交回伺服器以驗證是否與簡訊中原始傳送的內容匹配。

概念與用法

電話號碼通常被用作識別應用使用者的標識。簡訊經常被用來驗證該號碼是否屬於使用者。簡訊通常包含一個 OTP,使用者需要複製並貼上到應用中的表單中,以驗證他們擁有該號碼。這是一種相當笨拙的使用者體驗。

OTP 的使用場景包括:

  • 透過使用電話號碼作為 多因素身份驗證 系統的一部分來提高登入安全性。
  • 驗證敏感操作,例如付款。

WebOTP API 允許 Web 應用程式透過自動複製簡訊中的 OTP 並將其傳遞給應用程式來加快此驗證過程,前提是使用者已提供同意(大多數原生平臺都有等效的 API)。

請注意,OTP 繫結到傳送域。這是一個有用的安全限制,用於驗證 OTP 是否來自正確的來源,這可以減輕日常重新驗證期間網路釣魚攻擊的風險。

簡訊 OTP 的安全顧慮

簡訊 OTP 對於驗證電話號碼很有用,並且使用簡訊作為第二個因素肯定比沒有第二個因素要好。在某些地區,電子郵件地址和身份驗證器等其他識別符號並未得到廣泛使用,因此簡訊 OTP 非常普遍。

然而,簡訊的安全性不高。攻擊者可以偽造簡訊並劫持一個人的電話號碼。運營商可以在賬戶關閉後將電話號碼回收給新使用者。

因此,建議您如果可能,使用更強的身份驗證形式,例如基於 Web Authentication API 的解決方案,包括密碼和安全金鑰或通行金鑰。

WebOTP API 如何工作?

過程如下:

  1. 在需要電話號碼驗證的節點,應用客戶端會要求使用者在表單中輸入他們的電話號碼,然後將其提交給應用伺服器。
  2. 應用客戶端然後呼叫 navigator.credentials.get(),並附帶一個 otp 選項,指定 transport 型別為 "sms"。這會觸發從底層系統請求 OTP,其來源是一個從應用伺服器接收到的特殊格式的簡訊(包含 OTP 和應用的域名)。get() 呼叫是基於 Promise 的,並等待接收簡訊。
  3. 應用伺服器將簡訊傳送到指定的電話號碼。這必須在步驟 2 發生後立即進行。
  4. 當裝置收到簡訊時,如果其中包含應用的域名,瀏覽器會詢問使用者是否同意檢索/使用 OTP。例如,Chrome 會顯示一個對話方塊,請求使用者允許從簡訊中檢索 OTP;其他瀏覽器可能處理方式不同。如果使用者同意,get() 呼叫將以一個包含 OTP 的 OTPCredential 物件返回。
  5. 然後,您可以按需使用 OTP。典型用法是將其設定為應用客戶端驗證表單的值,然後提交表單,使過程儘可能無縫。
  6. 應用伺服器然後驗證回傳給它的 OTP 是否與它最初在簡訊中傳送的一致,如果一致,則完成過程(例如,登入使用者)。

簡訊格式

典型的簡訊看起來像這樣:

Your verification code is 123456.

@www.example.com #123456
  • 第一行和第二行空白行是可選的,用於人類可讀性。
  • 最後一行是強制性的。如果存在其他行,它必須是最後一行,並且必須由以下部分組成:
    • 呼叫 API 的網站 URL 的域名部分,前面加上一個 @
    • 後面跟著一個空格。
    • 後面跟著 OTP,前面加上一個井號(#)。

注意:提供的域名值不得包含 URL 方案、埠或其他未在上方顯示的 URL 要素。

如果 get() 方法由嵌入在 <iframe> 中的第三方網站呼叫,則簡訊結構應為:

Your verification code is 123456.

@top-level.example.com #123456 @embedded.com

在這種情況下,最後一行必須由以下部分組成:

  • 頂級域的域名部分,前面加上一個 @
  • 後面跟著一個空格。
  • 後面跟著 OTP,前面加上一個井號(#)。
  • 後面跟著一個空格。
  • 後面跟著嵌入域的域名部分,前面加上一個 @

控制對 API 的訪問

WebOTP 的可用性可以使用 Permissions Policy 進行控制,該策略指定了 otp-credentials 指令。此指令的預設允許列表值為 "self",這意味著預設情況下,這些方法可以在頂層文件上下文中用於。

您可以指定一個指令,允許在特定的跨域域中使用 WebOTP(即,在 <iframe> 中),如下所示:

http
Permissions-Policy: otp-credentials=(self "https://embedded.com")

或者您也可以直接在 <iframe> 上指定,如下所示:

html
<iframe src="https://embedded.com/..." allow="otp-credentials"> ... </iframe>

注意:在策略禁止使用 WebOTP get() 的地方,它返回的 Promise 將會因 SecurityError DOMException 而拒絕。

介面

OTPCredential

WebOTP get() 呼叫成功時返回;包含一個 code 屬性,其中包含檢索到的 OTP。

其他介面的擴充套件

CredentialsContainer.get()otp 選項

使用 otp 選項呼叫 get() 會指示使用者代理嘗試從底層系統的簡訊應用中檢索 OTP。

示例

在此示例中,當收到簡訊並用戶授予許可權後,會返回一個帶有 OTP 的 OTPCredential 物件。然後,此密碼會預填充到驗證表單欄位中,並提交表單。

嘗試使用手機進行此演示.

表單欄位包含一個值為 one-time-codeautocomplete 屬性。這對於 WebOTP API 的工作不是必需的,但值得包含。因此,即使 WebOTP API 在 Safari 中不受完全支援,當收到格式正確的簡訊時,Safari 也會提示使用者使用 OTP 自動填充此欄位。

html
<input type="text" autocomplete="one-time-code" inputmode="numeric" />

JavaScript 如下:

js
// Detect feature support via OTPCredential availability
if ("OTPCredential" in window) {
  const input = document.querySelector('input[autocomplete="one-time-code"]');
  if (!input) return;
  // Set up an AbortController to use with the OTP request
  const ac = new AbortController();
  const form = input.closest("form");
  if (form) {
    // Abort the OTP request if the user attempts to submit the form manually
    form.addEventListener("submit", (e) => {
      ac.abort();
    });
  }
  // Request the OTP via get()
  navigator.credentials
    .get({
      otp: { transport: ["sms"] },
      signal: ac.signal,
    })
    .then((otp) => {
      // When the OTP is received by the app client, enter it into the form
      // input and submit the form automatically
      input.value = otp.code;
      if (form) form.submit();
    })
    .catch((err) => {
      console.error(err);
    });
}

另一個使用 AbortController 的好方法是,在一段時間後取消 get() 請求。

js
setTimeout(() => {
  // abort after 30 seconds
  ac.abort();
}, 30 * 1000);

如果使用者分心或導航到其他地方,取消請求很重要,這樣他們就不會看到不再相關的許可權提示。

規範

規範
WebOTP API

瀏覽器相容性

另見