Xác minh số điện thoại trên web bằng API WebOTP

Giúp người dùng cung cấp các OTP nhận được qua SMS

API WebOTP là gì?

Ngày nay, hầu hết mọi người trên thế giới đều sở hữu một thiết bị di động và các nhà phát triển thường sử dụng số điện thoại làm giá trị nhận dạng cho người dùng dịch vụ của họ.

Có nhiều cách để xác minh số điện thoại, nhưng mật khẩu một lần (OTP) được tạo ngẫu nhiên qua SMS là một trong những cách phổ biến nhất. Việc gửi mã này trở lại máy chủ của nhà phát triển sẽ minh hoạ khả năng kiểm soát số điện thoại.

Ý tưởng này đã được triển khai trong nhiều trường hợp để đạt được:

  • Số điện thoại dùng làm giá trị nhận dạng cho người dùng. Khi bạn đăng ký một dịch vụ mới, một số trang web sẽ yêu cầu số điện thoại thay vì địa chỉ email và sử dụng số điện thoại đó làm mã nhận dạng tài khoản.
  • Xác minh 2 bước. Khi đăng nhập, một trang web sẽ yêu cầu gửi mã một lần qua SMS, ngoài mật khẩu hoặc hệ số kiến thức khác để tăng cường bảo mật.
  • Xác nhận khoản thanh toán. Khi người dùng đang thanh toán, việc yêu cầu mã một lần được gửi qua SMS có thể giúp xác minh ý định của họ.

Quy trình hiện tại sẽ gây phiền hà cho người dùng. Việc tìm một OTP trong tin nhắn SMS rồi sao chép và dán mã đó vào biểu mẫu sẽ rườm rà, làm giảm tỷ lệ chuyển đổi trong các hành trình trọng yếu của người dùng. Đơn giản hoá điều này đã là một yêu cầu lâu dài đối với web của nhiều nhà phát triển lớn nhất trên toàn cầu. Android có một API thực hiện chính xác việc này. iOSSafari cũng vậy.

API WebOTP cho phép ứng dụng nhận các thông báo có định dạng đặc biệt liên kết đến miền của ứng dụng. Từ đó, bạn có thể lập trình để lấy OTP từ tin nhắn SMS và xác minh số điện thoại cho người dùng dễ dàng hơn.

Xem ví dụ thực tiễn

Giả sử một người dùng muốn xác minh số điện thoại của họ qua một trang web. Trang web gửi tin nhắn văn bản cho người dùng qua SMS và người dùng nhập OTP từ tin nhắn để xác minh quyền sở hữu số điện thoại đó.

Với API WebOTP, các bước này chỉ đơn giản như một lần nhấn đối với người dùng, như được minh hoạ trong video. Khi tin nhắn văn bản đến, một bảng dưới cùng sẽ bật lên và nhắc người dùng xác minh số điện thoại. Sau khi nhấp vào nút Xác minh ở bảng dưới cùng, trình duyệt sẽ dán OTP vào biểu mẫu và biểu mẫu sẽ được gửi mà người dùng không cần nhấn Continue (Tiếp tục).

Hình ảnh bên dưới thể hiện toàn bộ quá trình này.

Sơ đồ API WebOTP

Hãy tự mình thử bản minh hoạ. Trợ lý không yêu cầu số điện thoại của bạn hoặc gửi tin nhắn SMS đến thiết bị của bạn, nhưng bạn có thể gửi tin nhắn từ thiết bị khác bằng cách sao chép văn bản hiển thị trong bản minh hoạ. Cách này hiệu quả vì không quan trọng người gửi là ai khi sử dụng API WebOTP.

  1. Truy cập vào https://web-otp.glitch.me trong Chrome 84 trở lên trên thiết bị Android.
  2. Gửi cho điện thoại của bạn tin nhắn văn bản SMS sau từ điện thoại khác.
Your OTP is: 123456.

@web-otp.glitch.me #12345

Bạn có nhận được SMS và thấy lời nhắc nhập mã vào khu vực nhập không? Đó là cách API WebOTP hoạt động cho người dùng.

Việc sử dụng API WebOTP bao gồm ba phần:

  • Thẻ <input> được chú thích đúng cách
  • JavaScript trong ứng dụng web của bạn
  • Nội dung tin nhắn được định dạng gửi qua SMS.

Trước tiên, tôi sẽ trình bày về thẻ <input>.

Chú thích thẻ <input>

Bản thân WebOTP hoạt động mà không cần chú thích HTML nào, nhưng để đảm bảo khả năng tương thích trên nhiều trình duyệt, bạn nên thêm autocomplete="one-time-code" vào thẻ <input> mà bạn muốn người dùng nhập OTP.

Điều này cho phép Safari 14 trở lên đề xuất người dùng tự động điền vào trường <input> bằng OTP khi họ nhận được một SMS có định dạng được mô tả trong phần Định dạng tin nhắn SMS mặc dù ứng dụng không hỗ trợ WebOTP.

HTML

<form>
  <input autocomplete="one-time-code" required/>
  <input type="submit">
</form>

Sử dụng API WebOTP

Vì WebOTP rất đơn giản, nên bạn chỉ cần sao chép và dán mã sau. Dù sao thì tôi cũng sẽ hướng dẫn bạn mọi việc.

JavaScript

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.log(err);
    });
  });
}

Phát hiện tính năng

Tính năng phát hiện tính năng giống như đối với nhiều API khác. Việc theo dõi sự kiện DOMContentLoaded sẽ chờ cây DOM sẵn sàng để truy vấn.

JavaScript

if ('OTPCredential' in window) {
  window.addEventListener('DOMContentLoaded', e => {
    const input = document.querySelector('input[autocomplete="one-time-code"]');
    if (!input) return;
    …
    const form = input.closest('form');
    …
  });
}

Xử lý OTP

Bản thân API WebOTP cũng đã đủ đơn giản. Sử dụng navigator.credentials.get() để nhận OTP. WebOTP thêm tuỳ chọn otp mới vào phương thức đó. Lớp này chỉ có một thuộc tính: transport, giá trị này phải là một mảng có chuỗi 'sms'.

JavaScript

    …
    navigator.credentials.get({
      otp: { transport:['sms'] }
      …
    }).then(otp => {
    …

Thao tác này sẽ kích hoạt luồng cấp quyền của trình duyệt khi có tin nhắn SMS đến. Nếu được cấp quyền, lời hứa được trả về sẽ phân giải bằng đối tượng OTPCredential.

Nội dung của đối tượng OTPCredential thu được

{
  code: "123456" // Obtained OTP
  type: "otp"  // `type` is always "otp"
}

Tiếp theo, hãy truyền giá trị OTP vào trường <input>. Việc gửi trực tiếp biểu mẫu sẽ loại bỏ bước yêu cầu người dùng nhấn vào nút.

JavaScript

    …
    navigator.credentials.get({
      otp: { transport:['sms'] }
      …
    }).then(otp => {
      input.value = otp.code;
      if (form) form.submit();
    }).catch(err => {
      console.error(err);
    });
    …

Đang huỷ thư

Trong trường hợp người dùng nhập OTP và gửi biểu mẫu theo cách thủ công, bạn có thể huỷ lệnh gọi get() bằng cách sử dụng một thực thể AbortController trong đối tượng options.

JavaScript

    …
    const ac = new AbortController();
    …
    if (form) {
      form.addEventListener('submit', e => {
        ac.abort();
      });
    }
    …
    navigator.credentials.get({
      otp: { transport:['sms'] },
      signal: ac.signal
    }).then(otp => {
    …

Định dạng tin nhắn SMS

Bản thân API này trông khá đơn giản, nhưng bạn nên biết một số điều trước khi sử dụng. Tin nhắn phải được gửi sau khi gọi navigator.credentials.get() và phải được nhận trên thiết bị đã gọi get(). Cuối cùng, thông báo phải tuân theo các định dạng sau:

  • Thông báo bắt đầu bằng văn bản (không bắt buộc) mà con người có thể đọc được, bao gồm một chuỗi từ 4 đến 10 ký tự bao gồm chữ và số, trong đó có ít nhất một số rời khỏi dòng cuối cùng của URL và OTP.
  • Phần miền của URL của trang web đã gọi API phải đứng sau @.
  • URL phải chứa ký hiệu dấu thăng ("#") theo sau là OTP.

Ví dụ:

Your OTP is: 123456.

@www.example.com #123456

Sau đây là một số ví dụ không hiệu quả:

Ví dụ về Văn bản SMS không đúng định dạng Lý do không giải quyết được vấn đề
Here is your code for @example.com #123456 @ dự kiến sẽ là ký tự đầu tiên của dòng cuối cùng.
Your code for @example.com is #123456 @ dự kiến sẽ là ký tự đầu tiên của dòng cuối cùng.
Your verification code is 123456

@example.com\t#123456
Dự kiến có một không gian duy nhất trong khoảng từ @host đến #code.
Your verification code is 123456

@example.com  #123456
Dự kiến có một không gian duy nhất trong khoảng từ @host đến #code.
Your verification code is 123456

@ftp://example.com #123456
Không thể bao gồm lược đồ URL.
Your verification code is 123456

@https://example.com #123456
Không thể bao gồm lược đồ URL.
Your verification code is 123456

@example.com:8080 #123456
Không thể bao gồm cổng.
Your verification code is 123456

@example.com/foobar #123456
Không thể bao gồm đường dẫn.
Your verification code is 123456

@example .com #123456
Không có khoảng trắng trong miền.
Your verification code is 123456

@domain-forbiden-chars-#%/:<>?@[] #123456
Không có ký tự bị cấm trong miền.
@example.com #123456

Mambo Jumbo
@host#code dự kiến sẽ là dòng cuối cùng.
@example.com #123456

App hash #oudf08lkjsdf834
@host#code dự kiến sẽ là dòng cuối cùng.
Your verification code is 123456

@example.com 123456
Thiếu #.
Your verification code is 123456

example.com #123456
Thiếu @.
Hi mom, did you receive my last text Thiếu @#.

Bản thu thử

Hãy thử nhiều thông báo bằng bản minh hoạ: https://web-otp.glitch.me

Bạn cũng có thể phát triển nhánh đó và tạo phiên bản của mình: https://glitch.com/edit/#!/web-otp.

Sử dụng WebOTP từ một iframe trên nhiều nguồn gốc

Việc nhập SMS OTP vào iframe nhiều nguồn gốc thường được dùng để xác nhận thanh toán, đặc biệt là với tính năng Bảo mật 3D. Có định dạng phổ biến để hỗ trợ các iframe nhiều nguồn gốc, API WebOTP phân phối các OTP liên kết với các nguồn gốc lồng nhau. Ví dụ:

  • Một người dùng truy cập vào shop.example để mua một đôi giày bằng thẻ tín dụng.
  • Sau khi nhập số thẻ tín dụng, nhà cung cấp dịch vụ thanh toán tích hợp sẽ hiển thị một biểu mẫu từ bank.example trong iframe yêu cầu người dùng xác minh số điện thoại để thanh toán nhanh.
  • bank.example gửi một tin nhắn SMS chứa OTP cho người dùng để họ có thể nhập nhằm xác minh danh tính của mình.

Để sử dụng API WebOTP từ bên trong iframe trên nhiều nguồn gốc, bạn cần thực hiện hai việc:

  • Chú thích cả nguồn gốc khung hình trên cùng và nguồn gốc iframe trong tin nhắn văn bản SMS.
  • Định cấu hình chính sách về quyền để cho phép iframe nhiều nguồn gốc nhận OTP trực tiếp từ người dùng.
API WebOTP trong một iframe đang hoạt động.

Bạn có thể dùng thử bản minh hoạ tại https://web-otp-iframe-demo.stackblitz.io.

Chú thích các nguồn gốc ràng buộc vào tin nhắn văn bản SMS

Khi API WebOTP được gọi từ trong một iframe, tin nhắn văn bản SMS phải bao gồm nguồn gốc khung hình trên cùng có đứng sau @, theo sau là OTP theo sau # và nguồn gốc iframe đặt sau @ ở dòng cuối.

Your verification code is 123456

@shop.example #123456 @bank.exmple

Định cấu hình chính sách về quyền

Để sử dụng WebOTP trong iframe trên nhiều nguồn gốc, trình nhúng phải cấp quyền truy cập vào API này thông qua chính sách về quyền otp-credentials nhằm tránh hành vi ngoài ý muốn. Nói chung có hai cách để đạt được mục tiêu này:

thông qua Tiêu đề HTTP:

Permissions-Policy: otp-credentials=(self "https://bank.example")

qua thuộc tính allow của iframe:

<iframe src="https://bank.example/…" allow="otp-credentials"></iframe>

Xem thêm ví dụ về cách chỉ định chính sách quyền .

Sử dụng WebOTP trên máy tính

Trong Chrome, WebOTP hỗ trợ nghe các tin nhắn SMS nhận được trên các thiết bị khác để hỗ trợ người dùng hoàn tất quy trình xác minh số điện thoại trên máy tính.

API WebOTP trên máy tính.

Tính năng này yêu cầu người dùng đăng nhập vào cùng một Tài khoản Google trên cả Chrome dành cho máy tính và Android Chrome.

Tất cả những gì nhà phát triển phải làm là triển khai API WebOTP trên trang web dành cho máy tính giống như cách họ thực hiện trên trang web dành cho thiết bị di động, nhưng không cần có thủ thuật đặc biệt nào.

Hãy tìm hiểu thêm chi tiết trong bài viết Xác minh số điện thoại trên máy tính bằng API WebOTP.

Câu hỏi thường gặp

Hộp thoại không xuất hiện mặc dù tôi đang gửi thư được định dạng đúng. Bạn gặp vấn đề gì?

Có một số lưu ý khi kiểm thử API:

  • Nếu số điện thoại của người gửi có trong danh bạ của người nhận, thì API này sẽ không được kích hoạt do thiết kế của SMS User Consent API cơ bản.
  • Nếu bạn đang sử dụng hồ sơ công việc trên thiết bị Android và WebOTP không hoạt động, hãy thử cài đặt và sử dụng Chrome trên hồ sơ cá nhân của bạn (tức là chính hồ sơ mà bạn nhận được tin nhắn SMS).

Kiểm tra lại định dạng để xem SMS của bạn có được định dạng chính xác không.

API này có tương thích giữa các trình duyệt khác nhau không?

Chromium và WebKit đã đồng ý về định dạng tin nhắn văn bản SMSApple đã công bố hỗ trợ Safari kể từ iOS 14 và macOS Big Sur. Mặc dù Safari không hỗ trợ API JavaScript WebOTP, nhưng bằng cách chú giải phần tử input bằng autocomplete=["one-time-code"], bàn phím mặc định sẽ tự động đề xuất bạn nhập OTP nếu tin nhắn SMS tuân thủ định dạng đó.

Sử dụng SMS làm cách xác thực có an toàn không?

Mặc dù OTP qua tin nhắn SMS rất hữu ích trong việc xác minh số điện thoại khi số được cung cấp lần đầu, nhưng bạn phải cẩn thận khi xác minh số điện thoại qua SMS để xác thực lại, vì các nhà mạng có thể xâm nhập và tái chế số điện thoại. WebOTP là một cơ chế xác thực lại và khôi phục tiện lợi, nhưng các dịch vụ nên kết hợp cơ chế này với các yếu tố bổ sung, chẳng hạn như thách thức về kiến thức hoặc sử dụng API xác thực web để xác thực hiệu quả.

Tôi có thể báo cáo lỗi ở đâu trong quá trình triển khai của Chrome?

Bạn có phát hiện thấy lỗi khi triển khai Chrome không?

  • Gửi lỗi tại https://new.crbug.com. Cung cấp càng nhiều thông tin chi tiết càng tốt, hướng dẫn đơn giản để tái tạo và đặt Thành phần thành Blink>WebOTP.

Tôi có thể trợ giúp tính năng này bằng cách nào?

Bạn có định sử dụng API WebOTP không? Nội dung hỗ trợ công khai của bạn giúp chúng tôi ưu tiên các tính năng và cho các nhà cung cấp trình duyệt khác biết tầm quan trọng của việc hỗ trợ họ. Hãy gửi một bài đăng trên Twitter tới @ChromiumDev kèm theo hashtag #WebOTP và cho chúng tôi biết vị trí cũng như cách bạn sử dụng bài đăng này.

Tài nguyên