แนวทางปฏิบัติแนะนำสำหรับแบบฟอร์ม SMS OTP

โดยปกติแล้ว ระบบจะขอให้ผู้ใช้ระบุรหัสผ่านแบบใช้ครั้งเดียว (OTP) เพื่อยืนยันตัวตนโดยการส่ง SMS กรณีการใช้งานบางส่วนสำหรับ OTP ทาง SMS ได้แก่

  • การตรวจสอบสิทธิ์แบบ 2 ปัจจัย นอกเหนือจากชื่อผู้ใช้และรหัสผ่านแล้ว คุณยังใช้ OTP ทาง SMS เป็นสัญญาณที่ชัดเจนได้ว่าบัญชีเป็นของบุคคลที่ได้รับ OTP ทาง SMS
  • การยืนยันหมายเลขโทรศัพท์ บริการบางอย่างใช้หมายเลขโทรศัพท์เป็นตัวระบุหลักของผู้ใช้ ในบริการดังกล่าว ผู้ใช้สามารถป้อนหมายเลขโทรศัพท์และ OTP ที่ได้รับทาง SMS เพื่อยืนยันตัวตน บางครั้งอาจใช้ร่วมกับ PIN เพื่อเป็นการตรวจสอบสิทธิ์แบบ 2 ปัจจัย
  • การกู้คืนบัญชี เมื่อผู้ใช้สูญเสียสิทธิ์เข้าถึงบัญชีของตนเอง ก็จำเป็นต้องมีวิธีกู้คืนบัญชี การส่งอีเมลไปยังอีเมลที่ลงทะเบียนไว้หรือการส่ง OTP ทาง SMS ไปยังหมายเลขโทรศัพท์เป็นวิธีการกู้คืนบัญชีที่พบบ่อย
  • การยืนยันการชำระเงิน ในระบบการชำระเงิน ธนาคารหรือผู้ออกบัตรเครดิตบางรายจะขอการตรวจสอบสิทธิ์เพิ่มเติมจากผู้ชำระเงินเพื่อเหตุผลด้านความปลอดภัย ซึ่งโดยทั่วไปแล้วจะใช้ OTP ทาง SMS เพื่อวัตถุประสงค์ดังกล่าว

อ่านต่อเพื่อดูแนวทางปฏิบัติแนะนำในการสร้างแบบฟอร์ม OTP ทาง SMS สำหรับกรณีการใช้งานเหล่านี้

เช็กลิสต์

หากต้องการมอบประสบการณ์การใช้งานที่ดีที่สุดแก่ผู้ใช้ด้วย OTP ทาง SMS ให้ทำตามขั้นตอนต่อไปนี้

  • ใช้องค์ประกอบ <input> กับรายการต่อไปนี้
    • type="text"
    • inputmode="numeric"
    • autocomplete="one-time-code"
  • ใช้ @BOUND_DOMAIN #OTP_CODE เป็นบรรทัดสุดท้ายของข้อความ SMS ที่มี OTP
  • ใช้ WebOTP API

ใช้องค์ประกอบ <input>

การใช้แบบฟอร์มที่มีองค์ประกอบ <input> เป็นแนวทางปฏิบัติแนะนำที่สำคัญที่สุดที่คุณทำตามได้ เนื่องจากใช้ได้ในทุกเบราว์เซอร์ แม้ว่าคำแนะนำอื่นๆ จากโพสต์นี้จะใช้ไม่ได้ในบางเบราว์เซอร์ แต่ผู้ใช้จะยังคงป้อนและส่ง OTP ด้วยตนเองได้

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

ต่อไปนี้เป็นแนวคิดบางส่วนที่จะช่วยให้ช่องป้อนข้อมูลใช้ประโยชน์จากฟังก์ชันการทำงานของเบราว์เซอร์ได้อย่างเต็มที่

type="text"

เนื่องจาก OTP มักเป็นตัวเลข 5 หรือ 6 หลัก การใช้ type="number" สำหรับช่องป้อนข้อมูลอาจดูเป็นเรื่องที่เข้าใจได้ง่ายเพราะจะเปลี่ยนแป้นพิมพ์บนอุปกรณ์เคลื่อนที่ให้เป็นตัวเลขเท่านั้น เราไม่แนะนำให้ทำเช่นนี้เนื่องจากเบราว์เซอร์คาดหวังว่าช่องป้อนข้อมูลจะเป็นตัวเลขที่นับได้ ไม่ใช่ลำดับของตัวเลขหลายตัว ซึ่งอาจทำให้เกิดลักษณะการทำงานที่ไม่คาดคิด การใช้ type="number" จะทำให้ปุ่มขึ้นและลงแสดงข้างช่องป้อนข้อมูล การกดปุ่มเหล่านี้จะเพิ่มหรือลดตัวเลข และอาจนำเลขศูนย์ที่อยู่ข้างหน้าออก

โปรดใช้ type="text" แทน การดำเนินการนี้จะไม่เปลี่ยนแป้นพิมพ์บนอุปกรณ์เคลื่อนที่ให้เป็นตัวเลขเท่านั้น แต่ก็ไม่เป็นไร เพราะเคล็ดลับถัดไปสำหรับการใช้ inputmode="numeric" จะทำหน้าที่นั้น

inputmode="numeric"

ใช้ inputmode="numeric" เพื่อเปลี่ยนแป้นพิมพ์บนอุปกรณ์เคลื่อนที่เป็นตัวเลขเท่านั้น

บางเว็บไซต์ใช้ type="tel" สำหรับช่องป้อนข้อมูล OTP เนื่องจากจะเปลี่ยนแป้นพิมพ์บนอุปกรณ์เคลื่อนที่เป็นตัวเลขเท่านั้น (รวมถึง * และ #) เมื่อโฟกัส วิธีนี้เคยใช้ในอดีตเมื่อ inputmode="numeric" ยังไม่ได้รับการรองรับอย่างแพร่หลาย เนื่องจาก Firefox เริ่มรองรับ inputmode="numeric" แล้ว จึงไม่จำเป็นต้องใช้แฮ็ก type="tel" ที่ไม่ถูกต้องในเชิงความหมาย

autocomplete="one-time-code"

แอตทริบิวต์ autocomplete ช่วยให้นักพัฒนาแอประบุสิทธิ์ที่เบราว์เซอร์มีในการให้ความช่วยเหลือเกี่ยวกับการเติมข้อความอัตโนมัติ และแจ้งให้เบราว์เซอร์ทราบเกี่ยวกับประเภทข้อมูลที่คาดว่าจะอยู่ในช่อง

เมื่อใช้ autocomplete="one-time-code" ทุกครั้งที่ผู้ใช้ได้รับข้อความ SMS ขณะที่แบบฟอร์มเปิดอยู่ ระบบปฏิบัติการจะแยกวิเคราะห์ OTP ใน SMS โดยใช้การวิเคราะห์พฤติกรรม และแป้นพิมพ์จะแนะนำ OTP ให้ผู้ใช้ป้อน โดยจะทำงานใน Safari 12 ขึ้นไปบน iOS, iPadOS และ macOS เท่านั้น แต่เราขอแนะนำอย่างยิ่งให้ใช้ เนื่องจากเป็นวิธีที่ดีกว่าในการปรับปรุงประสบการณ์การใช้งาน OTP ทาง SMS บนแพลตฟอร์มเหล่านั้น

autocomplete="one-time-code" ตอนทำกิจกรรม

autocomplete="one-time-code" ช่วยปรับปรุงประสบการณ์ของผู้ใช้ แต่คุณยังทำสิ่งอื่นๆ ได้อีกด้วยการตรวจสอบว่าข้อความ SMS เป็นไปตามรูปแบบข้อความที่เชื่อมโยงกับต้นทาง

แอตทริบิวต์ที่ไม่บังคับ

แอตทริบิวต์ที่ไม่บังคับมีดังนี้

อ่านแนวทางปฏิบัติแนะนำสำหรับแบบฟอร์มลงชื่อเข้าใช้เพื่อดูคำแนะนำเพิ่มเติม

จัดรูปแบบข้อความ SMS

ปรับปรุงประสบการณ์ของผู้ใช้ในการป้อน OTP โดยปรับให้สอดคล้องกับข้อกำหนดรหัสแบบครั้งเดียวที่เชื่อมโยงกับต้นทางซึ่งส่งทาง SMS

โดยหลักๆ แล้ว กฎรูปแบบมีดังนี้ จบข้อความ SMS ด้วยโดเมนผู้รับที่ขึ้นต้นด้วย @ และ OTP ที่ขึ้นต้นด้วย #

เช่น

Your OTP is 123456

@web-otp.example.com #123456

รูปแบบมาตรฐานสำหรับข้อความ OTP ช่วยให้การดึงข้อมูลทำได้ง่ายและเชื่อถือได้มากขึ้น การเชื่อมโยงรหัส OTP กับเว็บไซต์ทำให้หลอกลวงผู้ใช้ให้ระบุรหัสแก่เว็บไซต์ที่เป็นอันตรายได้ยากขึ้น

กฎการจัดรูปแบบที่แม่นยำ

กฎที่แน่นอนมีดังนี้

  • ข้อความจะขึ้นต้นด้วยข้อความที่มนุษย์อ่านได้ (ไม่บังคับ) ซึ่งมีสตริงอักขระที่เป็นตัวอักษรและตัวเลขคละกัน 4-10 ตัว โดยมีตัวเลขอย่างน้อย 1 ตัว และเว้นบรรทัดสุดท้ายไว้สำหรับ URL และ OTP
  • ส่วนโดเมนของ URL ของเว็บไซต์ที่เรียกใช้ API ต้องขึ้นต้นด้วย @
  • URL ต้องมี # ตามด้วย OTP จำนวนอักขระต้องไม่เกิน 140 ตัว

การใช้รูปแบบนี้มีประโยชน์ 2 ประการดังนี้

  • โดย OTP จะเชื่อมโยงกับโดเมน หากผู้ใช้อยู่ในโดเมนอื่นนอกเหนือจากที่ระบุไว้ในข้อความ SMS คำแนะนำ OTP จะไม่ปรากฏขึ้น นอกจากนี้ยังช่วยลดความเสี่ยงจากการโจมตีแบบฟิชชิงและการลักลอบใช้บัญชีที่อาจเกิดขึ้นได้ด้วย
  • ตอนนี้เบราว์เซอร์จะดึงข้อมูล OTP ได้อย่างน่าเชื่อถือโดยไม่ต้องพึ่งพาวิธีการเรียนรู้ที่ลึกลับและไม่แน่นอน

เมื่อเว็บไซต์ใช้ autocomplete="one-time-code", Safari ที่มี iOS 14 ขึ้นไปจะแนะนำ OTP ตามกฎเหล่านี้

รูปแบบข้อความ SMS นี้ยังเป็นประโยชน์ต่อเบราว์เซอร์อื่นๆ นอกเหนือจาก Safari ด้วย Chrome, Opera และ Vivaldi บน Android ยังรองรับกฎรหัสแบบใช้ครั้งเดียวที่เชื่อมโยงกับต้นทางด้วย WebOTP API ด้วย แม้ว่าจะไม่ได้ผ่าน autocomplete="one-time-code" ก็ตาม

ใช้ WebOTP API

WebOTP API ให้สิทธิ์เข้าถึง OTP ที่ได้รับในข้อความ SMS เมื่อเรียกใช้ navigator.credentials.get() ด้วยประเภท otp (OTPCredential) โดยที่ transport มี sms เว็บไซต์จะรอให้มีการส่ง SMS ที่สอดคล้องกับรหัสแบบใช้ครั้งเดียวที่เชื่อมโยงกับต้นทางและผู้ใช้ให้สิทธิ์เข้าถึง เมื่อส่ง OTP ไปยัง JavaScript แล้ว เว็บไซต์จะใช้ OTP ในแบบฟอร์มหรือ POST ไปยังเซิร์ฟเวอร์โดยตรงได้

navigator.credentials.get({
  otp: {transport:['sms']}
})
.then(otp => input.value = otp.code);
WebOTP API ในการใช้งานจริง

ดูวิธีใช้ WebOTP API โดยละเอียดในยืนยันหมายเลขโทรศัพท์บนเว็บด้วย WebOTP API หรือคัดลอกและวางข้อมูลโค้ดต่อไปนี้ ตรวจสอบว่าได้ตั้งค่าแอตทริบิวต์ action และ method ใน <form> แล้ว

// 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);
    });
  });
}