שיטות מומלצות לטופס OTP באמצעות SMS

איך מבצעים אופטימיזציה של טופס OTP ל-SMS ומשפרים את חוויית המשתמש

אחת הדרכים הנפוצות לאימות מספר הטלפון של משתמש היא לבקש ממנו לספק את ה-OTP (הסיסמה החד-פעמית) שנשלחת ב-SMS. יש כמה תרחישים לדוגמה לשימוש ב-OTP ב-SMS:

  • אימות דו-שלבי בנוסף לשם המשתמש ולסיסמה, אפשר להשתמש ב-OTP ל-SMS כאות חזק לכך שהחשבון נמצא בבעלות של מי שקיבל את ה-OTP ל-SMS.
  • אימות מספר טלפון בחלק מהשירותים, מספר הטלפון משמש כמזהה הראשי של המשתמש. בשירותים כאלה, המשתמשים יכולים להזין את מספר הטלפון ואת קוד האימות החד-פעמי (OTP) שקיבלו ב-SMS כדי להוכיח את הזהות שלהם. לפעמים הוא משולב עם מספר PIN כדי ליצור אימות דו-שלבי.
  • שחזור חשבון אם משתמש מאבד את הגישה לחשבון, צריכה להיות לו אפשרות לשחזר אותו. שיטות נפוצות לשחזור חשבון הן שליחת אימייל לכתובת האימייל הרשומה של המשתמש או שליחת סיסמה חד-פעמית ב-SMS למספר הטלפון שלו.
  • אישור תשלום: במערכות תשלומים, חלק מהבנקים או מנפיקי כרטיסי האשראי מבקשים מהמשלם אימות נוסף מטעמי אבטחה. לצורך כך נעשה שימוש נפוץ ב-OTP ב-SMS.

במאמר הזה מפורטות שיטות מומלצות ליצירת טופס OTP ל-SMS לתרחישים שלמעלה.

רשימת המשימות

כדי לספק את חוויית המשתמש הטובה ביותר עם OTP ב-SMS, יש לפעול לפי השלבים הבאים:

  • משתמשים ברכיב <input> עם:
    • type="text"
    • inputmode="numeric"
    • autocomplete="one-time-code"
  • משתמשים ב-@BOUND_DOMAIN #OTP_CODE כשורה האחרונה של הודעת ה-SMS עם קוד האימות החד-פעמי.
  • משתמשים ב-WebOTP API.

שימוש ברכיב <input>

השיטה המומלצת החשובה ביותר היא להשתמש בטופס עם רכיב <input>, כי הוא פועל בכל הדפדפנים. גם אם ההצעות האחרות במאמר הזה לא יפעלו בדפדפן מסוים, המשתמש עדיין יוכל להזין את קוד האימות החד-פעמי ולשלוח אותו באופן ידני.

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

ריכזנו כאן כמה רעיונות שיעזרו לכם להפיק את המקסימום מהפונקציונליות של הדפדפן בשדה הקלט.

type="text"

מאחר שמספרי OTP הם בדרך כלל מספרים של חמישה או שישה ספרות, השימוש ב-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 בזמן שהטופס פתוח, מערכת ההפעלה תנתח את קוד האימות החד-פעמי ב-SMS באופן היוריסטי והמקלדת תציע למשתמש להזין את קוד האימות החד-פעמי. התכונה פועלת רק ב-Safari מגרסה 12 ואילך ב-iOS, ב-iPadOS וב-macOS, אבל מומלץ מאוד להשתמש בה כי היא דרך קלה לשפר את חוויית השימוש ב-OTP ב-SMS בפלטפורמות האלה.

'autocomplete="one-time-code"' בפעולה.

autocomplete="one-time-code" משפרת את חוויית המשתמש, אבל אפשר לעשות עוד דברים על ידי הבטחת התאימות של הודעת ה-SMS לפורמט ההודעה המקושר למקור.

עיצוב הטקסט של ה-SMS

כדי לשפר את חוויית המשתמש בהזנת קוד OTP, כדאי לפעול בהתאם למפרט של קודים חד-פעמיים שמקושרים למקור ונשלחים ב-SMS.

כלל הפורמט פשוט: מסתיימים את הודעת ה-SMS עם הדומיין של הנמען, לפניו @, ואת הסיסמה החד-פעמית, לפניה #.

לדוגמה:

Your OTP is 123456

@web-otp.glitch.me #123456

שימוש בפורמט סטנדרטי להודעות OTP מאפשר לחלץ מהן קודים בקלות ובאופן מהימן יותר. שיוך של קודי OTP לאתרים מקשה על הטעיית משתמשים כדי שיספקו קוד לאתרים זדוניים.

לשימוש בפורמט הזה יש כמה יתרונות:

  • ה-OTP יהיה קשור לדומיין. אם המשתמש נמצא בדומיינים שונים מהדומיין שצוין בהודעת ה-SMS, ההצעה ל-OTP לא תופיע. כך גם מפחיתים את הסיכון למתקפות פישינג ולפריצות אפשריות לחשבון.
  • הדפדפן יוכל עכשיו לחלץ את ה-OTP באופן מהימן, בלי להסתמך על שיטות ניתוח נתונים סתריות ופגיעות.

כשאתר משתמש ב-autocomplete="one-time-code", דפדפן Safari עם iOS מגרסה 14 ואילך יציע את קוד האימות החד-פעמי בהתאם לכללים שלמעלה.

פורמט ההודעות ב-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, אפשר להשתמש בו בטופס באתר או לשלוח אותו ישירות לשרת באמצעות 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);
    });
  });
}

תמונה מאת Jason Leung ב-Unsplash.