إثبات ملكية أرقام الهواتف على الويب باستخدام WebOTP API

مساعدة المستخدمين في ما يتعلّق بالرموز المؤقتة التي يتم استلامها عبر الرسائل القصيرة

ما هي واجهة برمجة التطبيقات WebOTP API؟

في الوقت الحالي، يمتلك معظم الأشخاص في العالم جهازًا جوّالاً، ويستخدم المطوّرون بشكل شائع أرقام الهواتف كمعرّف لمستخدمي خدماتهم.

هناك طرق متنوعة لإثبات ملكية أرقام الهواتف، ولكن كلمة المرور الصالحة لمرة واحدة (OTP) التي يتم إنشاؤها عشوائيًا وإرسالها عبر الرسائل القصيرة هي إحدى الطرق الأكثر شيوعًا. يُثبت إرسال هذا الرمز إلى خادم المطوّر إمكانية التحكّم في رقم الهاتف.

تمّ استخدام هذه الفكرة في العديد من السيناريوهات لتحقيق ما يلي:

  • رقم الهاتف كمعرّف للمستخدم: عند الاشتراك في خدمة جديدة، تطلب بعض المواقع الإلكترونية رقم هاتف بدلاً من عنوان بريد إلكتروني، و تستخدمه كمعرّف للحساب.
  • التحقّق بخطوتين: عند تسجيل الدخول، يطلب الموقع الإلكتروني إدخال رمز صالح لمرة واحدة يتم إرساله عبر رسالة قصيرة (SMS) بالإضافة إلى كلمة مرور أو عامل معرفة آخر لتعزيز الأمان.
  • تأكيد الدفع: عندما يُجري المستخدم عملية دفع، يمكن أن يساعد طلب رمز صالح لمرة واحدة يتم إرساله عبر الرسائل القصيرة في التحقّق من نية المستخدم.

تتسبب العملية الحالية في حدوث مشاكل للمستخدمين. إنّ العثور على رمز مميّز مؤقت في رسالة SMS، ثم نسخه ولصقه في النموذج هو عملية مزعجة، ما يؤدي إلى خفض معدّلات الإحالات الناجحة في رحلات المستخدِمين المهمة. وقد كان تسهيل هذا الإجراء مطلبًا قديمًا على الويب من العديد من أكبر المطوّرين في العالم. يحتوي Android على واجهة برمجة تطبيقات تؤدي هذا الإجراء بالضبط. وينطبق ذلك أيضًا على iOS و Safari.

تتيح واجهة برمجة التطبيقات WebOTP API لتطبيقك تلقّي رسائل بتنسيق خاص مرتبط بنطاق تطبيقك. ومن خلال ذلك، يمكنك الحصول على كلمة مرور صالحة لمرة واحدة من رسالة SMS برمجيًا وإثبات ملكية رقم هاتف المستخدم بسهولة أكبر.

أمثلة واقعية

لنفترض أنّ أحد المستخدمين يريد إثبات ملكية رقم هاتفه باستخدام موقع إلكتروني. يُرسِل الموقع الإلكتروني رسالة نصية إلى المستخدم عبر الرسائل القصيرة، ويُدخِل المستخدم كلمة المرور لمرة واحدة الواردة في الرسالة لإثبات ملكية رقم الهاتف.

باستخدام WebOTP API، يمكن للمستخدم تنفيذ هذه الخطوات بنقرة واحدة، كما هو موضح في الفيديو. عند وصول الرسالة النصية، تنبثق ورقة سفلية تطلب من المستخدم إثبات ملكية رقم هاتفه. بعد النقر على الزر التحقّق في اللوحة السفلية، يلصق المتصفّح رمز OTP في النموذج ويتم إرسال النموذج بدون أن يحتاج المستخدم إلى الضغط على متابعة.

يمكنك الاطّلاع على مخطّط العملية بأكملها في الصورة أدناه.

مخطّط WebOTP API البياني

جرِّب الإصدار التجريبي بنفسك. لا يطلب التطبيق معرفة رقم هاتفك أو إرسال رسالة SMS إلى جهازك، ولكن يمكنك إرسال رسالة من جهاز آخر عن طريق نسخ النص المعروض في العرض التجريبي. ويعمل هذا الإجراء لأنّه لا يهمّ هوية المُرسِل عند استخدام WebOTP API.

  1. انتقِل إلى https://web-otp.glitch.me في Chrome 84 أو الإصدارات الأحدث على جهاز Android.
  2. أرسِل إلى هاتفك الرسالة النصية التالية من هاتف آخر.
Your OTP is: 123456.

@web-otp.glitch.me #12345

هل تلقّيت الرسالة القصيرة وظهرت لك رسالة تطلب منك إدخال الرمز في حقل الإدخال؟ هذه هي الطريقة التي تعمل بها واجهة برمجة التطبيقات WebOTP API للمستخدمين.

يتألف استخدام واجهة برمجة التطبيقات WebOTP API من ثلاثة أجزاء:

  • علامة <input> تمّت إضافة تعليقات توضيحية لها بشكلٍ صحيح
  • JavaScript في تطبيق الويب
  • نص رسالة منسَّق تم إرساله عبر الرسائل القصيرة

سأتناول علامة <input> أولاً.

إضافة تعليق توضيحي إلى علامة <input>

يعمل WebOTP نفسه بدون أي تعليق توضيحي بتنسيق HTML، ولكن من أجل التوافق مع جميع المتصفّحات، أنصحك بشدة بإضافة autocomplete="one-time-code" إلى علامة <input> حيث تتوقّع أن يُدخل المستخدم مفتاح OTP.

يتيح ذلك لمتصفّح Safari 14 أو الإصدارات الأحدث أن يقترح على المستخدم ملء الحقل <input> تلقائيًا باستخدام مفتاح OTP عند استلام رسالة SMS بالتنسيق الموضّح في تنسيق رسالة SMS، على الرغم من أنّه لا يتيح استخدام WebOTP.

HTML

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

استخدام WebOTP API

بما أنّ WebOTP بسيط، يكفي نسخ الرمز التالي ولصقه لتنفيذ الإجراء. سأشرح لك ما يحدث على أي حال.

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

رصد الميزات

إنّ عملية رصد الميزات هي نفسها في العديد من واجهات برمجة التطبيقات الأخرى. سيؤدي الاستماع إلى حدث DOMContentLoaded إلى الانتظار إلى أن تصبح شجرة نموذج العناصر في المستند جاهزة للبحث.

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

معالجة كلمة المرور لمرة واحدة

إنّ واجهة برمجة التطبيقات WebOTP API نفسها بسيطة بما يكفي. استخدِم navigator.credentials.get() للحصول على كلمة المرور لمرة واحدة. تضيف WebOTP خيار otp جديدًا إلى هذه الطريقة. تحتوي على سمة واحدة فقط: transport، ويجب أن تكون قيمتها مصفوفة تحتوي على السلسلة 'sms'.

JavaScript

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

يؤدي ذلك إلى بدء عملية الحصول على أذونات المتصفّح عند وصول رسالة قصيرة. في حال منح الإذن، يتم حلّ الوعد المعروض باستخدام عنصر OTPCredential.

محتوى عنصر OTPCredential الذي تم الحصول عليه

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

بعد ذلك، نقْل قيمة رمز التحقّق المؤقت إلى الحقل <input>. سيؤدي إرسال النموذج مباشرةً إلى إلغاء الخطوة التي تتطلّب من المستخدم النقر على زر.

JavaScript

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

إيقاف الرسالة

في حال أدخل المستخدم رمز OTP يدويًا وأرسل النموذج، يمكنك إلغاء get() الاتصال باستخدام مثيل AbortController في كائن 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 => {
    

تنسيق رسالة SMS

من المفترض أن تكون واجهة برمجة التطبيقات نفسها بسيطة بما يكفي، ولكن هناك بعض الأمور التي يجب معرفته قبل استخدامها. يجب إرسال الرسالة بعد استدعاء navigator.credentials.get() ويجب استلامها على الجهاز الذي تم استدعاء get() عليه. أخيرًا، يجب أن تلتزم الرسالة بالتنسيق التالي:

  • تبدأ الرسالة بنص (اختياري) يمكن لشخص عادي قراءته ويحتوي على سلسلة أبجدية رقمية من أربعة إلى عشرة أحرف مع رقم واحد على الأقل، ويترك السطر الأخير لعنوان URL ورمز OTP.
  • يجب أن يسبق @ جزء النطاق من عنوان URL للموقع الإلكتروني الذي استدعى واجهة برمجة التطبيقات.
  • يجب أن يحتوي عنوان URL على علامة الباوند (#) متبوعة برمز مفتاح المرور المؤقت.

على سبيل المثال:

Your OTP is: 123456.

@www.example.com #123456

في ما يلي أمثلة على المحتوى السيئ:

مثال على نص رسالة SMS بتنسيق غير صحيح سبب عدم نجاح هذا الإجراء
Here is your code for @example.com #123456 من المتوقّع أن يكون @ هو الحرف الأول من السطر الأخير.
Your code for @example.com is #123456 من المتوقّع أن يكون @ هو الحرف الأول من السطر الأخير.
Your verification code is 123456

@example.com\t#123456
من المتوقّع أن تفصل مسافة واحدة بين @host و#code.
Your verification code is 123456

@example.com  #123456
من المتوقّع أن تكون هناك مسافة واحدة بين @host و#code.
Your verification code is 123456

@ftp://example.com #123456
لا يمكن تضمين مخطّط عنوان URL.
Your verification code is 123456

@https://example.com #123456
لا يمكن تضمين مخطّط عنوان URL.
Your verification code is 123456

@example.com:8080 #123456
لا يمكن تضمين المنفذ.
Your verification code is 123456

@example.com/foobar #123456
لا يمكن تضمين المسار.
Your verification code is 123456

@example .com #123456
لا توجد مسافات بيضاء في النطاق.
Your verification code is 123456

@domain-forbiden-chars-#%/:<>?@[] #123456
عدم تضمين أحرف محظورة في النطاق
@example.com #123456

Mambo Jumbo
من المتوقّع أن يكون @host و#code هما السطر الأخير.
@example.com #123456

App hash #oudf08lkjsdf834
من المتوقّع أن يكون @host و#code هما السطر الأخير.
Your verification code is 123456

@example.com 123456
لا تتوفّر السمة #.
Your verification code is 123456

example.com #123456
لا تتوفّر السمة @.
Hi mom, did you receive my last text لا يتوفّر العمودان @ و#.

إصدارات تجريبية

جرِّب رسائل مختلفة باستخدام الإصدار التجريبي: https://web-otp.glitch.me

يمكنك أيضًا إنشاء نسخة منه وإنشاء نسختك: https://glitch.com/edit/#!/web-otp.

استخدام WebOTP من إطار iframe متعدد المصادر

يتم عادةً استخدام إدخال رمز مصادقة مؤقت عبر الرسائل القصيرة في إطار iframe من مصدر مختلف لتأكيد الدفع، خاصةً مع ميزة 3D Secure. توفّر WebOTP API تنسيقًا شائعًا للسماح باستخدام علامات iframe من مصادر متعددة، كما توفّر رموز OTP مرتبطة بمصادر متداخلة. على سبيل المثال:

  • يزور مستخدم الموقع الإلكتروني shop.example لشراء حذاء باستخدام بطاقة ائتمان.
  • بعد إدخال رقم بطاقة الائتمان، يعرض مقدّم خدمة الدفع المدمج bank.example نموذجًا في إطار iframe يطلب من المستخدم إثبات ملكية رقم هاتفه من أجل إتمام الدفع بسرعة.
  • تُرسِل bank.example رسالة قصيرة إلى المستخدم تتضمّن كلمة مرور صالحة لمرة واحدة (OTP) كي يتمكّن من إدخالها لإثبات هويته.

لاستخدام WebOTP API من داخل إطار iframe من مصدر مختلف، عليك إجراء أمرَين:

  • أضِف تعليقات توضيحية على كلّ من مصدر الإطار العلوي ومصدر iframe في محتوى الرسالة القصيرة.
  • عليك ضبط سياسة الأذونات للسماح لإطار iframe من مصدر مختلف بتلقّي رمز OTP من المستخدم مباشرةً.
استخدام WebOTP API ضمن إطار iframe

يمكنك تجربة الإصدار التجريبي على الرابط https://web-otp-iframe-demo.stackblitz.io.

إضافة تعليقات توضيحية إلى مصادر البيانات المرتبطة بالرسالة النصية

عند استدعاء WebOTP API من داخل إطار iframe، يجب أن تشمل الرسالة النصية المرسَلة عبر الرسائل القصيرة مصدر الإطار العلوي مسبوقًا برمز @ متبوعًا برمز OTP مسبوقًا برمز # ومصدر إطار iframe مسبوقًا برمز @ في السطر الأخير.

Your verification code is 123456

@shop.example #123456 @bank.exmple

ضبط "سياسة الأذونات"

لاستخدام WebOTP في إطار iframe من مصدر مختلف، على مُدرِج المحتوى منح إذن الوصول إلى واجهة برمجة التطبيقات هذه من خلال سياسة أذونات بيانات اعتماد otp لتجنُّب أي سلوك غير مقصود. بشكل عام، هناك طريقتان لتحقيق هذا الهدف:

من خلال عنوان HTTP:

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

عبر سمة iframe allow:

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

اطّلِع على مزيد من الأمثلة عن كيفية تحديد سياسة أذونات .

استخدام WebOTP على الكمبيوتر المكتبي

في Chrome، تتيح تقنية WebOTP الاستماع إلى الرسائل القصيرة الواردة على الأجهزة الأخرى لمساعدة المستخدمين في إكمال عملية إثبات ملكية رقم الهاتف على الكمبيوتر المكتبي.

WebOTP API على الكمبيوتر المكتبي

تتطلّب هذه الميزة من المستخدم تسجيل الدخول إلى حساب Google نفسه على كلٍّ من Chrome لأجهزة الكمبيوتر المكتبي وChrome لأجهزة Android.

ما على المطوّرين سوى تنفيذ WebOTP API على موقعهم الإلكتروني المخصّص لأجهزة الكمبيوتر المكتبي، بالطريقة نفسها التي ينفّذون بها ذلك على موقعهم الإلكتروني المخصّص للأجهزة الجوّالة، ولكن ليس هناك أي حيل خاصة مطلوب تنفيذها.

اطّلِع على مزيد من التفاصيل في مقالة إثبات ملكية رقم هاتف على الكمبيوتر المكتبي باستخدام WebOTP API.

الأسئلة الشائعة

لا يظهر مربّع الحوار على الرغم من أنّني أرسل رسالة بتنسيق صحيح. ما هي المشكلة؟

هناك بعض التحذيرات عند اختبار واجهة برمجة التطبيقات:

  • إذا كان رقم هاتف المُرسِل مُدرَجًا في قائمة جهات اتصال المستلِم، لن يتم تنشيط واجهة برمجة التطبيقات هذه بسبب تصميم SMS User Consent API الأساسية.
  • إذا كنت تستخدم ملف عمل على جهاز Android ولم يعمل رمز WebOTP، جرِّب تثبيت Chrome واستخدامه على ملفك الشخصي بدلاً من ذلك (أي الملف الشخصي نفسه الذي تتلقّى فيه رسائل SMS).

راجِع التنسيق لمعرفة ما إذا كان تنسيق الرسالة القصيرة صحيحًا.

هل هذه الواجهة متوافقة مع المتصفحات المختلفة؟

اتّفق فريقا Chromium وWebKit على تنسيق الرسائل النصية القصيرة SMS، وأعلنت Apple أنّ متصفّح Safari سيتيح هذا التنسيق بدءًا من الإصدار iOS 14 ونظام التشغيل macOS Big Sur. على الرغم من أنّ Safari لا يتيح استخدام WebOTP JavaScript API، إلا أنّه من خلال إضافة تعليق توضيحي إلى عنصر input باستخدام autocomplete=["one-time-code"]، تقترح الكتابة التلقائية إدخال رمز OTP تلقائيًا إذا كانت رسالة SMS متوافقة مع التنسيق.

هل من الآمن استخدام الرسائل القصيرة كطريقة للمصادقة؟

على الرغم من أنّ رمز التحقّق المرسَل عبر الرسائل القصيرة مفيد لإثبات ملكية رقم الهاتف عند تقديمه لأول مرة، يجب استخدام ميزة إثبات ملكية رقم الهاتف عبر الرسائل القصيرة بعناية عند إعادة التحقّق من الملكية، لأنّ شركات الجوّال يمكنها الاستيلاء على أرقام الهواتف وإعادة استخدامها. تُعدّ WebOTP آلية إعادة مصادقة واسترداد ملائمة، ولكن يجب أن تدمج الخدمات هذه الآلية مع عوامل إضافية، مثل اختبار معلومات، أو استخدام Web Authentication API لإجراء مصادقة قوية.

أين يمكنني الإبلاغ عن الأخطاء في عملية تنفيذ Chrome؟

هل رصدت خطأ في عملية تنفيذ Chrome؟

  • يمكنك إرسال بلاغ عن خلل على الرابط crbug.com. يُرجى تضمين أكبر قدر ممكن من التفاصيل وتعليمات بسيطة لإعادة إنتاج المشكلة، ويجب ضبط المكوّنات على Blink>WebOTP.

كيف يمكنني المساعدة في تحسين هذه الميزة؟

هل تخطّط لاستخدام واجهة برمجة التطبيقات WebOTP API؟ يساعدنا دعمك العلني في تحديد أولويات الميزات، ويُظهر لموفّري المتصفّحات الآخرين مدى أهمية توفيرها. أرسِل تغريدة إلى ‎@ChromiumDev باستخدام الهاشتاغ #WebOTP وأطلِعنا على مكان استخدامك للميزة وطريقة استخدامك لها.

الموارد