Các phương pháp hay nhất về biểu mẫu OTP qua tin nhắn SMS

Tìm hiểu cách tối ưu hoá biểu mẫu OTP qua tin nhắn SMS và cải thiện trải nghiệm người dùng.

Yêu cầu người dùng cung cấp OTP (mật khẩu một lần) qua SMS là một cách phổ biến để xác nhận số điện thoại của người dùng. Có một vài trường hợp sử dụng đối với OTP qua tin nhắn SMS:

  • Xác thực hai yếu tố. Ngoài tên người dùng và mật khẩu, OTP qua tin nhắn SMS có thể được sử dụng dưới dạng tín hiệu mạnh mẽ cho thấy tài khoản thuộc sở hữu của người đã nhận được tin nhắn SMS OTP.
  • Xác minh số điện thoại. Một số dịch vụ dùng số điện thoại làm giá trị nhận dạng chính của người dùng. Trong các dịch vụ như vậy, người dùng có thể nhập số điện thoại và OTP nhận được qua SMS để chứng minh danh tính của mình. Đôi khi, mã PIN được kết hợp với mã PIN để tạo thành tính năng xác thực hai yếu tố.
  • Khôi phục tài khoản. Khi người dùng mất quyền truy cập vào tài khoản của họ, cần có cách để khôi phục tài khoản đó. Gửi email đến địa chỉ email đã đăng ký hoặc gửi OTP qua SMS đến số điện thoại của họ là các phương thức khôi phục tài khoản phổ biến.
  • Xác nhận thanh toán Trong hệ thống thanh toán, một số ngân hàng hoặc công ty phát hành thẻ tín dụng yêu cầu người thanh toán xác thực bổ sung vì lý do bảo mật. OTP qua tin nhắn SMS thường được sử dụng cho mục đích đó.

Bài đăng này giải thích các phương pháp hay nhất để tạo biểu mẫu OTP qua tin nhắn SMS cho các trường hợp sử dụng ở trên.

Danh sách kiểm tra

Để mang lại trải nghiệm tốt nhất cho người dùng bằng SMS OTP, hãy làm theo các bước sau:

  • Sử dụng phần tử <input> với:
    • type="text"
    • inputmode="numeric"
    • autocomplete="one-time-code"
  • Sử dụng @BOUND_DOMAIN #OTP_CODE làm dòng cuối cùng của tin nhắn SMS OTP.
  • Sử dụng API WebOTP.

Dùng phần tử <input>

Sử dụng biểu mẫu có phần tử <input> là phương pháp hay nhất quan trọng nhất mà bạn có thể làm theo vì biểu mẫu này hoạt động trên mọi trình duyệt. Ngay cả khi các đề xuất khác trong bài đăng này không hoạt động trên một số trình duyệt, người dùng vẫn có thể nhập và gửi OTP theo cách thủ công.

<form action="/verify-otp" method="POST">
  <input type="text"
         inputmode="numeric"
         autocomplete="one-time-code"
         pattern="\d{6}"
         required>
</form>

Sau đây là một vài ý tưởng để đảm bảo trường nhập dữ liệu hoạt động hiệu quả nhất với chức năng của trình duyệt.

type="text"

Vì OTP thường là các số gồm 5 hoặc 6 chữ số, nên việc sử dụng type="number" cho trường nhập dữ liệu có vẻ trực quan vì nó chỉ thay đổi bàn phím di động thành số. Bạn không nên thực hiện việc này vì trình duyệt dự kiến trường đầu vào là một số đếm được thay vì một chuỗi gồm nhiều số. Điều này có thể gây ra hành vi không mong muốn. Việc sử dụng type="number" sẽ khiến các nút mũi tên lên và xuống hiển thị bên cạnh trường nhập dữ liệu; việc nhấn các nút này sẽ làm tăng hoặc giảm số và có thể xoá các số 0 trước đó.

Thay vào đó, hãy sử dụng type="text". Thao tác này sẽ không chuyển bàn phím trên thiết bị di động thành chỉ số, nhưng không sao cả vì mẹo tiếp theo để sử dụng inputmode="numeric" sẽ thực hiện công việc đó.

inputmode="numeric"

Sử dụng inputmode="numeric" để thay đổi bàn phím cho thiết bị di động thành chỉ số.

Một số trang web sử dụng type="tel" cho các trường nhập OTP vì tính năng này cũng chuyển bàn phím thiết bị di động sang chỉ số (bao gồm cả *#) khi lấy tiêu điểm. Kiểu tấn công này đã được sử dụng trước đây khi inputmode="numeric" chưa được hỗ trợ rộng rãi. Vì Firefox đã bắt đầu hỗ trợ inputmode="numeric", nên bạn không cần phải sử dụng cách tấn công type="tel" không chính xác về mặt ngữ nghĩa.

autocomplete="one-time-code"

Thuộc tính autocomplete cho phép nhà phát triển chỉ định quyền mà trình duyệt phải có để hỗ trợ tính năng tự động hoàn thành và thông báo cho trình duyệt về loại thông tin dự kiến có trong trường đó.

Với autocomplete="one-time-code", bất cứ khi nào người dùng nhận được tin nhắn SMS trong khi một biểu mẫu đang mở, hệ điều hành sẽ phân tích cú pháp OTP trong SMS theo phương pháp phỏng đoán và bàn phím sẽ đề xuất OTP để người dùng nhập. Tính năng này chỉ hoạt động trên Safari 12 trở lên trên iOS, iPadOS và macOS. Tuy nhiên, bạn nên sử dụng công cụ này vì đây là một cách dễ dàng giúp cải thiện trải nghiệm SMS OTP trên các nền tảng đó.

`autocomplete="one-time-code"` trong thực tế.

autocomplete="one-time-code" cải thiện trải nghiệm người dùng, nhưng bạn cũng có thể làm nhiều việc hơn bằng cách đảm bảo rằng tin nhắn SMS tuân thủ định dạng tin nhắn liên kết theo nguồn gốc.

Định dạng văn bản SMS

Cải thiện trải nghiệm người dùng khi nhập OTP bằng cách điều chỉnh cho phù hợp với quy cách mã một lần gắn với nguồn gốc được gửi qua SMS.

Quy tắc định dạng rất đơn giản: Hãy hoàn tất tin nhắn SMS bằng miền của người nhận đứng trước @ và OTP đứng sau #.

Ví dụ:

Your OTP is 123456

@web-otp.glitch.me #123456

Việc sử dụng định dạng chuẩn cho thông báo OTP giúp việc trích xuất mã từ các thông báo này dễ dàng hơn và đáng tin cậy hơn. Việc liên kết mã OTP với trang web khiến người dùng khó có thể lừa người dùng cung cấp mã cho các trang web độc hại.

Việc sử dụng định dạng này mang lại một số lợi ích:

  • OTP sẽ được liên kết với miền. Nếu người dùng đang sử dụng các miền không phải là miền được chỉ định trong tin nhắn SMS, thì đề xuất OTP sẽ không xuất hiện. Điều này cũng giúp giảm thiểu nguy cơ bị tấn công lừa đảo và chiếm đoạt tài khoản.
  • Giờ đây, trình duyệt sẽ có thể trích xuất OTP một cách đáng tin cậy mà không phụ thuộc vào các thông tin phỏng đoán bí ẩn và không rõ ràng.

Khi một trang web sử dụng autocomplete="one-time-code", Safari chạy iOS 14 trở lên sẽ đề xuất OTP theo các quy tắc nêu trên.

Định dạng tin nhắn SMS này cũng làm lợi cho các trình duyệt khác ngoài Safari. Chrome, Opera và Vivaldi trên Android cũng hỗ trợ quy tắc mã một lần ràng buộc nguồn gốc bằng API WebOTP, mặc dù không thông qua autocomplete="one-time-code".

Sử dụng API WebOTP

WebOTP API cung cấp quyền truy cập vào OTP nhận được trong tin nhắn SMS. Bằng cách gọi navigator.credentials.get() với loại otp (OTPCredential) trong đó transport bao gồm sms, trang web sẽ đợi một tin nhắn SMS tuân thủ mã một lần ràng buộc nguồn gốc được gửi và cấp quyền truy cập cho người dùng. Sau khi OTP được chuyển vào JavaScript, trang web có thể sử dụng OTP dưới dạng biểu mẫu hoặc POST trực tiếp lên máy chủ.

navigator.credentials.get({
  otp: {transport:['sms']}
})
.then(otp => input.value = otp.code);
API WebOTP trong thực tế.

Tìm hiểu chi tiết cách sử dụng API WebOTP trong bài viết Xác minh số điện thoại trên web bằng API WebOTP hoặc sao chép và dán đoạn mã sau. (Hãy đảm bảo rằng phần tử <form> đã được thiết lập đúng cách thuộc tính actionmethod.)

// Feature detection
if ('OTPCredential' in window) {
  window.addEventListener('DOMContentLoaded', e => {
    const input = document.querySelector('input[autocomplete="one-time-code"]');
    if (!input) return;
    // Cancel the WebOTP API if the form is submitted manually.
    const ac = new AbortController();
    const form = input.closest('form');
    if (form) {
      form.addEventListener('submit', e => {
        // Cancel the WebOTP API.
        ac.abort();
      });
    }
    // Invoke the WebOTP API
    navigator.credentials.get({
      otp: { transport:['sms'] },
      signal: ac.signal
    }).then(otp => {
      input.value = otp.code;
      // Automatically submit the form when an OTP is obtained.
      if (form) form.submit();
    }).catch(err => {
      console.log(err);
    });
  });
}

Ảnh của Jason Leung trên Unsplash.