إنشاء مفتاح مرور لتسجيل الدخول بدون كلمة مرور

تجعل مفاتيح المرور حسابات المستخدمين أكثر أمانًا وبساطة وسهولة في الاستخدام.

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

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

آلية العمل

يمكن أن يُطلب من المستخدم إنشاء مفتاح مرور في إحدى الحالتَين التاليتَين:

  • عندما يسجّل مستخدم الدخول باستخدام كلمة مرور
  • عندما يسجِّل مستخدم الدخول باستخدام مفتاح مرور من جهاز آخر (أي أنّ authenticatorAttachment هو cross-platform).
  • في صفحة مخصَّصة يمكن للمستخدمين من خلالها إدارة مفاتيح المرور

لإنشاء مفتاح مرور، عليك استخدام واجهة برمجة التطبيقات WebAuthn API.

المكونات الأربعة لتدفق تسجيل مفتاح المرور هي:

  • الخلفية: خادم الخلفية الذي يحتوي على قاعدة بيانات الحسابات التي تخزِّن المفتاح العام والبيانات الوصفية الأخرى عن مفتاح المرور
  • الواجهة الأمامية: الواجهة الأمامية التي تتواصل مع المتصفّح وتُرسِل requests for fetch (طلبات استرجاع البيانات) إلى الواجهة الخلفية
  • المتصفح: متصفح المستخدم الذي يشغّل جافا سكريبت.
  • مصادقة: أداة مصادقة المستخدم التي تنشئ ملف تعريف البريد الإلكتروني وتخزِّنه وقد يشمل ذلك مدير كلمات المرور على الجهاز نفسه الذي يستخدمه المتصفح (على سبيل المثال، عند استخدام Windows Hello) أو على جهاز آخر مثل الهاتف.
مخطّط تسجيل مفتاح المرور

في ما يلي خطوات إضافة مفتاح مرور جديد إلى حساب مستخدم حالي:

  1. سجَّل مستخدم الدخول إلى الموقع الإلكتروني.
  2. بعد تسجيل دخول المستخدم، يطلب إنشاء مفتاح مرور على واجهة المستخدم، على سبيل المثال، من خلال الضغط على زر "إنشاء مفتاح مرور".
  3. تطلب الواجهة الأمامية معلومات من الخلفي لإنشاء مفتاح مرور، مثل معلومات العميل وتحدّي وأرقام تعريف بيانات الاعتماد المطلوب استبعادها.
  4. يتصل الواجهة الأمامية بخدمة navigator.credentials.create() لإنشاء مفتاح مرور. يعرض هذا الطلب وعدًا.
  5. يتم إنشاء مفتاح مرور بعد موافقة المستخدم باستخدام قفل شاشة الجهاز. يتم حلّ الوعد ويتم عرض بيانات اعتماد المفتاح العام في الواجهة الأمامية.
  6. تُرسِل الواجهة الأمامية بيانات اعتماد المفتاح العام إلى الواجهة الخلفية وتخزِّن معرّف بيانات الاعتماد والمفتاح العام المرتبط بحساب المستخدم لعمليات مصادقة المستقبلية.

التوافق

تتوافق معظم المتصفحات مع WebAuthn، ولكن هناك بعض الثغرات الصغيرة. يُرجى الرجوع إلى الوصول إلى الأجهزة - مفاتيح المرور.dev لمعرفة مجموعة المتصفّحات وأنظمة التشغيل التي تتيح إنشاء مفتاح مرور.

إنشاء مفتاح مرور جديد

في ما يلي كيفية عمل الواجهة الأمامية عند تلقّي طلب لإنشاء مفتاح مرور جديد.

رصد الميزات

قبل عرض زر "إنشاء مفتاح مرور جديد"، تأكَّد مما يلي:

  • يتوافق المتصفّح مع WebAuthn باستخدام PublicKeyCredential.

توافق المتصفّح

  • Chrome: 67.
  • Edge: 18.
  • Firefox: 60
  • ‫Safari: 13

المصدر

  • يتيح الجهاز مصادقة المنصة (يمكنه إنشاء مفتاح مرور و المصادقة باستخدام مفتاح المرور) باستخدام PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable().

توافق المتصفّح

  • Chrome: 67
  • Edge: 18.
  • Firefox: 60
  • ‫Safari: 13

المصدر

توافق المتصفّح

  • Chrome: 108.
  • الحافة: 108.
  • Firefox: 119.
  • ‫Safari: 16

المصدر

// Availability of `window.PublicKeyCredential` means WebAuthn is usable.  
// `isUserVerifyingPlatformAuthenticatorAvailable` means the feature detection is usable.  
// `​​isConditionalMediationAvailable` means the feature detection is usable.  
if (window.PublicKeyCredential &&  
    PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable &&  
    PublicKeyCredential.​​isConditionalMediationAvailable) {  
  // Check if user verifying platform authenticator is available.  
  Promise.all([  
    PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(),  
    PublicKeyCredential.​​isConditionalMediationAvailable(),  
  ]).then(results => {  
    if (results.every(r => r === true)) {  
      // Display "Create a new passkey" button  
    }  
  });  
}  

لن تتوفّر مفاتيح المرور في هذا المتصفّح إلى أن يتم استيفاء جميع الشروط. من المفترض ألا يظهر الزر "إنشاء مفتاح مرور جديد" إلى ذلك الحين.

جلب معلومات مهمة من الخلفية

عندما ينقر المستخدم على الزر، يمكنك جلب المعلومات المهمة للاتصال بـ navigator.credentials.create() من الخلفية:

  • challenge: تحدّي ينشئه الخادم في ArrayBuffer لهذا التسجيل. هذا الحقل مطلوب، ولكن لا يتم استخدامه أثناء التسجيل ما لم يتم إجراء عملية إقرار، وهو موضوع متقدم لا يتم تناوله هنا.
  • user.id: معرّف فريد للمستخدم. يجب أن تكون هذه القيمة ArrayBuffer لا تتضمّن معلومات تحديد الهوية الشخصية، مثل عناوين البريد الإلكتروني أو أسماء المستخدمين. ستعمل بشكل جيد قيمة عشوائية تبلغ 16 بايت يتم إنشاؤها لكل حساب.
  • user.name: يجب أن يحتوي هذا الحقل على معرّف فريد للحساب يمكن للمستخدم التعرّف عليه، مثل عنوان بريده الإلكتروني أو اسمه المستخدِم. سيتم عرض هذا في أداة اختيار الحسابات. (في حال استخدام اسم مستخدم، يُرجى استخدام القيمة نفسها الواردة في مصادقة كلمة المرور).
  • user.displayName: هذا الحقل هو اسم مطلوب للحساب وأكثر ملاءمةً للمستخدم. ولا يلزم أن يكون فريدًا، ويمكن أن يكون الاسم الذي يختاره المستخدم. إذا لم يتضمن موقعك الإلكتروني قيمة مناسبة لتضمينها هنا، أدخِل سلسلة فارغة. يمكن عرض ذلك في أداة اختيار الحساب اعتمادًا على المتصفّح
  • excludeCredentials: يمنع تسجيل الجهاز نفسه من خلال تقديم قائمة بأرقام تعريف مستندات الاعتماد التي سبق تسجيلها. من المفترض أن يتضمّن عضو transports، إذا تم توفيره، نتيجة استدعاء getTransports() أثناء تسجيل كل بيانات اعتماد.

طلب WebAuthn API لإنشاء مفتاح مرور

يُرجى الاتصال على navigator.credentials.create() لإنشاء مفتاح مرور جديد. تُعرِض واجهة برمجة التطبيقات وعدًا بالانتظار إلى أن يتفاعل المستخدم مع مربّع حوار مشروط.

توافق المتصفّح

  • Chrome: 60
  • الحافة: 18.
  • Firefox: 60
  • ‫Safari: 13

المصدر

const publicKeyCredentialCreationOptions = {
  challenge: *****,
  rp: {
    name: "Example",
    id: "example.com",
  },
  user: {
    id: *****,
    name: "john78",
    displayName: "John",
  },
  pubKeyCredParams: [{alg: -7, type: "public-key"},{alg: -257, type: "public-key"}],
  excludeCredentials: [{
    id: *****,
    type: 'public-key',
    transports: ['internal'],
  }],
  authenticatorSelection: {
    authenticatorAttachment: "platform",
    requireResidentKey: true,
  }
};

const credential = await navigator.credentials.create({
  publicKey: publicKeyCredentialCreationOptions
});

// Encode and send the credential to the server for verification.  

المعلمات غير الموضّحة أعلاه هي:

  • rp.id: معرّف مقدّم الخدمة هو نطاق ويمكن لموقع إلكتروني تحديد نطاقه أو لاحقة قابلة للتسجيل. على سبيل المثال، إذا كان مصدر نقطة الانطلاق هو https://login.example.com:1337، يمكن أن يكون رقم تعريف نقطة الانطلاق هو login.example.com أو example.com. إذا تم تحديد معرّف مقدّم الخدمة على النحو التالي: example.com، يمكن للمستخدم المصادقة على login.example.com أو على أي نطاقات فرعية على example.com.

  • rp.name: اسم الجهة المحظورة

  • pubKeyCredParams: يحدِّد هذا الحقل خوارزميات المفاتيح العامة المتوافقة مع موفِّر خدمات الربط. ننصحك بضبطها على [{alg: -7, type: "public-key"},{alg: -257, type: "public-key"}]. يحدِّد ذلك توافق ECDSA مع P-256 وRSA PKCS#1، ما يوفّر تغطية كاملة.

  • authenticatorSelection.authenticatorAttachment: اضبط هذا الخيار على "platform" إذا كان إنشاء مفتاح المرور هذا ترقية من كلمة مرور، مثلاً في عرض ترويجي بعد تسجيل الدخول. يشير الرمز "platform" إلى أنّ العميل يريد مصادقة نظام أساسي (مصادقة مضمّنة في جهاز النظام الأساسي) لن تطلب منه إدخال مفتاح أمان USB مثلاً. يتوفّر للمستخدم خيار أبسط لإنشاء مفتاح مرور.

  • authenticatorSelection.requireResidentKey: اضبطها على قيمة منطقية "true". تخزِّن بيانات الاعتماد القابلة للاكتشاف (مفتاح الإقامة) معلومات المستخدم في مفتاح المرور وتسمح للمستخدمين باختيار الحساب عند المصادقة. اطّلِع على مزيد من المعلومات عن بيانات الاعتماد القابلة للاكتشاف في مقالة نظرة تفصيلية على بيانات الاعتماد القابلة للاكتشاف .

  • authenticatorSelection.userVerification: يشير إلى ما إذا كان إثبات هوية المستخدم باستخدام قفل شاشة الجهاز هو "required" أو "preferred" أو "discouraged". القيمة التلقائية هي "preferred"، ما يعني أنّ معتمِد الهوية قد يتخطّى عملية إثبات هوية المستخدم. اضبط السمة على "preferred" أو احذف السمة.

إرسال بيانات اعتماد المفتاح العام التي تم إرجاعها إلى الواجهة الخلفية

بعد أن يوافق المستخدم على استخدام قفل شاشة الجهاز، يتم إنشاء مفتاح مرور ويتم حلّ الوعد من خلال عرض عنصر PublicKeyCredential في الواجهة الأمامية.

يمكن رفض الوعد لأسباب مختلفة. يمكنك معالجة هذه الأخطاء من خلال التحقّق من سمة name لعنصر Error:

  • InvalidStateError: سبق أن تم إنشاء مفتاح مرور على الجهاز. لن يظهر للمستخدم مربّع حوار بشأن خطأ، ويجب ألا يتعامل الموقع الإلكتروني مع ذلك على أنّه خطأ، لأنّ المستخدم أراد تسجيل الجهاز المحلي وتم تسجيله.
  • NotAllowedError: ألغى المستخدم العملية.
  • الاستثناءات الأخرى: حدث خطأ غير متوقّع. يعرض المتصفح مربع حوار خطأ للمستخدم.

يحتوي عنصر بيانات اعتماد المفتاح العام على السمات التالية:

  • id: رقم تعريف بترميز Base64URL لمفتاح المرور الذي تم إنشاؤه. يساعد رقم التعريف هذا المتصفّح في تحديد ما إذا كان مفتاح مرور مطابق متوفّرًا في الجهاز عند المصادقة. يجب تخزين هذه القيمة في قاعدة البيانات في الخلفية.
  • rawId: نسخة ArrayBuffer من معرّف بيانات الاعتماد.
  • response.clientDataJSON: بيانات العميل بترميز ArrayBuffer
  • response.attestationObject: عنصر شهادة مُشفَّر بتنسيق ArrayBuffer يحتوي هذا الرمز على معلومات مهمة، مثل رقم تعريف مقدّم الطلبات والعلامات والمفتاح العام.
  • authenticatorAttachment: تعرض القيمة "platform" عند إنشاء بيانات الاعتماد هذه على جهاز مزوّد بمفتاح مرور.
  • type: يتم ضبط هذا الحقل دائمًا على "public-key".

إذا كنت تستخدم مكتبة للتعامل مع كائن بيانات اعتماد المفتاح العام في الخلفية، ننصحك بإرسال الكائن بأكمله إلى الواجهة الخلفية بعد ترميزه جزئيًا باستخدام base64url.

حفظ بيانات الاعتماد

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

يمكنك بعد ذلك تخزين المعلومات التي تم استرجاعها من بيانات الاعتماد في قاعدة البيانات لاستخدامها في المستقبل. تتضمّن القائمة التالية بعض السمات الشائعة التي يجب حفظها:

  • رقم تعريف بيانات الاعتماد (المفتاح الأساسي)
  • رقم تعريف المستخدم
  • المفتاح العام

تتضمّن بيانات اعتماد المفتاح العام أيضًا المعلومات التالية التي قد تحتاج إلى حفظها في قاعدة البيانات:

يُرجى اتّباع تعليمات أكثر تفصيلاً في صفحة تسجيل مفتاح المرور من جهة الخادم

لمصادقة المستخدم، يُرجى الاطّلاع على مقالة تسجيل الدخول باستخدام مفتاح مرور من خلال ميزة preenchimento automático (الملء التلقائي) للنموذج.

الموارد