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

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

تاريخ النشر: 12 أكتوبر 2022، تاريخ آخر تعديل: 09 أبريل 2026

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

تتم مزامنة مفاتيح المرور على جميع الأجهزة باستخدام مقدّمي خدمات مفاتيح المرور، مثل "مدير كلمات المرور في Google" و"سلسلة مفاتيح iCloud".

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

طريقة إنشاء مفتاح مرور

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

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

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

لإنشاء مفتاح مرور، يمكنك استخدام WebAuthn API.

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

  • الخادم الخلفي: يخزّن تفاصيل حساب المستخدم، بما في ذلك المفتاح العام.
  • واجهة المستخدم: تتواصل مع المتصفّح وتجلب البيانات اللازمة من الخلفية.
  • المتصفّح: يشغّل JavaScript ويتفاعل مع WebAuthn API.
  • مقدّم مفتاح المرور: ينشئ مفتاح المرور ويخزّنه. ويكون ذلك عادةً مدير كلمات مرور، مثل "مدير كلمات المرور في Google"، أو مفتاح أمان.
عملية إنشاء مفتاح مرور وتسجيله
عملية إنشاء مفتاح مرور وتسجيله

قبل إنشاء مفتاح مرور، تأكَّد من أنّ النظام يستوفي الشروط الأساسية التالية:

  • يتم إثبات ملكية حساب المستخدم من خلال طريقة آمنة (على سبيل المثال، البريد الإلكتروني أو تأكيد الحساب عبر الهاتف أو اتحاد الهوية) خلال فترة زمنية قصيرة ومناسبة.

  • يمكن أن يتواصل كل من الواجهة الأمامية والخلفية بشكل آمن لتبادل بيانات الاعتماد.

  • يتوافق المتصفّح مع WebAuthn وإمكانية إنشاء مفتاح مرور.

يمكننا أن نوضّح لك كيفية التحقّق من معظمها في الأقسام التالية.

بعد أن يستوفي النظام هذه الشروط، يتم اتّباع الخطوات التالية لإنشاء مفتاح مرور:

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

تضمن هذه العملية توفير عملية تسجيل آمنة وسلسة باستخدام مفتاح المرور للمستخدمين.

نقاط التوافق

تتوافق معظم المتصفحات مع WebAuthn، مع بعض الثغرات البسيطة. يمكنك الاطّلاع على passkeys.dev لمعرفة تفاصيل حول توافق المتصفّح ونظام التشغيل.

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

لإنشاء مفتاح مرور جديد، يجب أن تتّبع الواجهة الأمامية العملية التالية:

  1. التحقّق من التوافق
  2. استرجاع المعلومات من الواجهة الخلفية
  3. استدعاء WebAuth API لإنشاء مفتاح مرور
  4. أرسِل المفتاح العام الذي تم إرجاعه إلى الخلفية.
  5. احفظ بيانات الاعتماد.

توضّح الأقسام التالية كيفية إجراء ذلك.

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

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

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

Browser Support

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

Source

  • يتوافق المتصفّح مع ميزة رصد الإمكانات باستخدام PublicKeyCredential.getClientCapabilities().

Browser Support

  • Chrome: 133.
  • Edge: 133.
  • Firefox: 135.
  • Safari: 17.4.

Source

  • يتوافق المتصفّح مع واجهة المستخدم الشرطية في WebAuthn مع conditionalGet.

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

يوضّح مقتطف الرمز التالي كيفية التحقّق من التوافق قبل عرض الخيارات المتعلّقة بمفاتيح المرور.

if (window.PublicKeyCredential && PublicKeyCredential.getClientCapabilities) {
  const capabilities = await PublicKeyCredential.getClientCapabilities();
  if (capabilities.conditionalGet === true &&
      capabilities.passkeyPlatformAuthenticator === true) {
    // The browser supports passkeys and the conditional UI.
  }
}

في هذا المثال، يجب ألا يظهر الزر إنشاء مفتاح مرور جديد إلا إذا تم استيفاء جميع الشروط.

استرجاع المعلومات من الخلفية

عندما ينقر المستخدم على الزر، استرجِع المعلومات المطلوبة من الخلفية لاستدعاء navigator.credentials.create().

يوضّح مقتطف الرمز التالي عنصر JSON يتضمّن المعلومات المطلوبة لاستدعاء navigator.credentials.create():

// Example `PublicKeyCredentialCreationOptions` contents
{
  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,
  }
}

تحتوي أزواج المفتاح والقيمة في العنصر على المعلومات التالية:

  • challenge: تمثّل هذه السمة تحديًا من إنشاء الخادم في ArrayBuffer لعملية التسجيل هذه.
  • rp.id: يمكن لمعرّف RP (معرّف الجهة المعتمِدة) ونطاق وموقع إلكتروني تحديد إما نطاقه أو لاحقة قابلة للتسجيل. على سبيل المثال، إذا كان مصدر RP هو https://login.example.com:1337، يمكن أن يكون معرّف RP إما login.example.com أو example.com. إذا تم تحديد معرّف RP على أنّه example.com، يمكن للمستخدم إجراء المصادقة على login.example.com أو على أي نطاقات فرعية على example.com. يمكنك الاطّلاع على مقالة السماح بإعادة استخدام مفتاح المرور على مواقعك الإلكترونية من خلال طلبات المنشأ المرتبط لمزيد من المعلومات حول هذا الموضوع.
  • rp.name: اسم الجهة المحظورة (RP) تم إيقاف هذا الحقل نهائيًا في المستوى 3 من WebAuthn، ولكن تم تضمينه لأسباب تتعلق بالتوافق.
  • user.id: معرّف مستخدم فريد في ArrayBuffer، يتم إنشاؤه عند إنشاء الحساب. ويجب أن يكون دائمًا، على عكس اسم المستخدم الذي يمكن تعديله. يحدّد معرّف المستخدم حسابًا، ولكن يجب ألا يحتوي على أي معلومات تكشف الهوية الشخصية (PII). من المحتمل أنّ لديك رقم تعريف المستخدم في نظامك، ولكن إذا لزم الأمر، أنشئ رقم تعريف مخصّصًا لمفاتيح المرور فقط للحفاظ على خلوّه من أي معلومات تكشف الهوية الشخصية.
  • user.name: معرّف فريد للحساب يمكن للمستخدم التعرّف عليه، مثل عنوان بريده الإلكتروني أو اسم المستخدم. سيظهر هذا الاسم في أداة اختيار الحساب.
  • user.displayName: اسم مطلوب وأكثر ملاءمة للمستخدمين للحساب. ليس من الضروري أن يكون الاسم فريدًا، ويمكن أن يكون الاسم الذي اختاره المستخدم. إذا لم يكن موقعك الإلكتروني يتضمّن قيمة مناسبة لإدراجها هنا، يمكنك إدخال سلسلة فارغة. قد يظهر هذا الخيار في أداة اختيار الحساب حسب المتصفّح.
  • pubKeyCredParams: تحدّد هذه السمة خوارزميات المفتاح العام المتوافقة مع الجهة المعتمِدة (RP). ننصحك بضبطها على [{alg: -7, type: "public-key"},{alg: -257, type: "public-key"}]. يحدّد ذلك إمكانية استخدام ECDSA مع P-256 وRSA PKCS#1، ويوفّر استخدام هذين الخيارين تغطية كاملة.
  • excludeCredentials: قائمة بمعرّفات بيانات الاعتماد المسجّلة مسبقًا. يمنع تسجيل الجهاز نفسه مرّتين من خلال تقديم قائمة بمعرّفات بيانات الاعتماد التي تم تسجيلها. يجب أن يحتوي عنصر transports member، إذا تم توفيره، على نتيجة استدعاء getTransports() أثناء تسجيل كل بيانات اعتماد.
  • authenticatorSelection.authenticatorAttachment: اضبط هذه القيمة على "platform" مع hint: ['client-device'] إذا كان إنشاء مفتاح المرور هذا يمثّل ترقية من كلمة مرور، مثلاً في عرض ترويجي بعد تسجيل الدخول. يشير "platform" إلى أنّ الجهة المعتمدة تريد أداة مصادقة مدمجة في الجهاز (أداة مصادقة مدمجة في جهاز النظام الأساسي) لا تطلب، على سبيل المثال، إدخال مفتاح أمان USB. يتوفّر للمستخدم خيار أبسط لإنشاء مفتاح مرور.
  • استبدِل authenticatorSelection.requireResidentKey بقيمة منطقية true. بيانات اعتماد قابلة للاكتشاف (مفتاح مقيم) تخزّن معلومات المستخدم في مفتاح المرور وتتيح للمستخدمين اختيار الحساب عند المصادقة.
  • authenticatorSelection.userVerification: توضّح هذه السمة ما إذا كانت عملية إثبات هوية المستخدم باستخدام قفل شاشة الجهاز "required" أو "preferred" أو "discouraged". القيمة التلقائية هي "preferred"، ما يعني أنّ أداة المصادقة قد تتخطّى عملية إثبات هوية المستخدم. اضبط القيمة على "preferred" أو احذف السمة.

ننصح بإنشاء العنصر على الخادم، وترميز ArrayBuffer باستخدام Base64URL، ثم استرجاعه من الواجهة الأمامية. بهذه الطريقة، يمكنك فك ترميز الحمولة باستخدام PublicKeyCredential.parseCreationOptionsFromJSON() وتمريرها مباشرةً إلى navigator.credentials.create().

يوضّح مقتطف الرمز التالي كيفية استرداد المعلومات اللازمة لإنشاء مفتاح مرور وفك ترميزها.

// Fetch an encoded `PubicKeyCredentialCreationOptions` from the server.
const _options = await fetch('/webauthn/registerRequest');

// Deserialize and decode the `PublicKeyCredentialCreationOptions`.
const decoded_options = JSON.parse(_options);
const options = PublicKeyCredential.parseCreationOptionsFromJSON(decoded_options);
...

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

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

Browser Support

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

Source

// Invoke WebAuthn to create a passkey.
const credential = await navigator.credentials.create({
  publicKey: options
});

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

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

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

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

يحتوي كائن بيانات اعتماد المفتاح العام على الخصائص التالية:

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

ترميز الكائن باستخدام طريقة .toJSON() وتحويله إلى سلسلة باستخدام JSON.stringify() ثم إرساله إلى الخادم

...

// Encode and serialize the `PublicKeyCredential`.
const _result = credential.toJSON();
const result = JSON.stringify(_result);

// Encode and send the credential to the server for verification.  
const response = await fetch('/webauthn/registerResponse', {
  method: 'post',
  credentials: 'same-origin',
  body: result
});
...

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

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

يمكنك بعد ذلك تخزين المعلومات التي تم استرجاعها من بيانات الاعتماد في قاعدة البيانات لاستخدامها في المستقبل.

تتضمّن القائمة التالية السمات المقترَحة لحفظها:

  • معرّف بيانات الاعتماد: معرّف بيانات الاعتماد الذي تم عرضه مع بيانات اعتماد المفتاح العام.
  • اسم الشهادة: اسم الشهادة سمِّه باسم مقدّم مفتاح المرور الذي تم إنشاؤه من خلاله، ويمكن تحديد ذلك استنادًا إلى AAGUID.
  • رقم تعريف المستخدم: رقم تعريف المستخدم المستخدَم لإنشاء مفتاح المرور.
  • المفتاح العام: المفتاح العام الذي تم عرضه مع بيانات اعتماد المفتاح العام. وهو مطلوب للتحقّق من تأكيد مفتاح المرور.
  • تاريخ الإنشاء ووقته: يتم تسجيل تاريخ إنشاء مفتاح المرور ووقته. ويفيد ذلك في تحديد مفتاح المرور.
  • تاريخ ووقت آخر استخدام: يسجّل هذا الحقل آخر تاريخ ووقت استخدم فيهما المستخدم مفتاح المرور لتسجيل الدخول. ويفيد ذلك في تحديد مفتاح المرور الذي استخدمه المستخدم (أو لم يستخدمه).
  • استبدِل AAGUID بمعرّف فريد لموفّر مفتاح المرور.
  • علامة أهلية النسخ الاحتياطي: تكون القيمة true إذا كان الجهاز مؤهلاً لمزامنة مفاتيح المرور. تساعد هذه المعلومات المستخدمين في التعرّف على مفاتيح المرور التي يمكن مزامنتها وتلك المرتبطة بالجهاز (التي لا يمكن مزامنتها) في صفحة إدارة مفاتيح المرور.

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

إرسال إشارة في حال تعذُّر التسجيل

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

لمنع حدوث ذلك، يمكنك إرسال إشارة إلى موفّر مفتاح المرور باستخدام Signal API. من خلال طلب PublicKeyCredential.signalUnknownCredential() باستخدام معرّف RP ومعرّف بيانات اعتماد، يمكن لموفّر RP إبلاغ موفّر مفتاح المرور بأنّه تمت إزالة بيانات الاعتماد المحدّدة أو أنّها غير متوفّرة. يعود إلى مقدّم مفتاح المرور تحديد كيفية التعامل مع هذه الإشارة، ولكن في حال توفّرها، من المتوقّع أن تتم إزالة مفتاح المرور المرتبط بها.

// Detect authentication failure due to lack of the credential
if (response.status === 404) {
  // Feature detection
  if (PublicKeyCredential.signalUnknownCredential) {
    await PublicKeyCredential.signalUnknownCredential({
      rpId: "example.com",
      credentialId: "vI0qOggiE3OT01ZRWBYz5l4MEgU0c7PmAA" // base64url encoded credential ID
    });
  } else {
    // Encourage the user to delete the passkey from the password manager nevertheless.
    ...
  }
}

لمزيد من المعلومات حول Signal API، يُرجى الاطّلاع على مقالة الحفاظ على اتساق مفاتيح المرور مع بيانات الاعتماد على خادمك باستخدام Signal API.

إرسال إشعار إلى المستخدم

يساعد إرسال إشعار (مثل رسالة إلكترونية) عند تسجيل مفتاح مرور المستخدمين في رصد محاولات الوصول غير المصرّح بها إلى الحساب. إذا أنشأ مهاجم مفتاح مرور بدون علم المستخدم، سيظل مفتاح المرور متاحًا لإساءة الاستخدام في المستقبل، حتى بعد تغيير كلمة المرور. يُنبّه الإشعار المستخدم ويساعد في منع حدوث ذلك.

قائمة التحقق

  • يجب إثبات هوية المستخدم (يُفضّل استخدام البريد الإلكتروني أو طريقة آمنة) قبل السماح له بإنشاء مفتاح مرور.
  • منع إنشاء مفاتيح مرور مكرّرة لمزوّد مفاتيح المرور نفسه باستخدام excludeCredentials
  • احفظ AAGUID لتحديد موفّر مفتاح المرور ولتسمية بيانات الاعتماد للمستخدم.
  • تشير هذه السمة إلى ما إذا كانت محاولة تسجيل مفتاح مرور قد تعذّرت بسبب الخطأ PublicKeyCredential.signalUnknownCredential().
  • إرسال إشعار إلى المستخدم بعد إنشاء مفتاح مرور وتسجيله في حسابه

الموارد

الخطوة التالية: تسجيل الدخول باستخدام مفتاح مرور من خلال ميزة "الملء التلقائي للنماذج"