يوضّح هذا الدليل بالتفصيل كيفية تسجيل مفتاح مرور تلقائيًا وبشكل غير مرئي للمستخدم فور تسجيل الدخول بنجاح باستخدام كلمة مرور، ما يقلّل من الصعوبات ويزيد من معدّل استخدام مفاتيح المرور.
اللحظة المناسبة لبدء المحادثة
يجب عدم تفعيل ميزة الإنشاء التلقائي لمفاتيح المرور (المعروفة أيضًا باسم "الإنشاء المشروط" أو "الترويج الصامت بعد تسجيل الدخول") إلا بعد تسجيل الدخول الكامل والناجح الذي يتضمّن كلمة مرور.
- لا تحاول إنشاء حسابات مشروطة لعمليات تسجيل الدخول بدون كلمة مرور (مثل الروابط السحرية أو كلمات المرور الصالحة لمرة واحدة عبر الرسائل القصيرة أو توحيد الهوية).
- إذا كانت المصادقة المتعدّدة العوامل مطلوبة، عليك الانتظار حتى تنجح جميع العوامل قبل بدء الإنشاء المشروط.
- تأكَّد من أنّ جلسة المستخدم صالحة ومصادَق عليها ونشطة قبل إرسال طلبات إلى نقاط النهاية الخاصة بإنشاء المحتوى.
خطوات التنفيذ
1. إلغاء إجراءات الملء التلقائي السابقة
إذا كانت صفحة تسجيل الدخول تستخدم ميزة الملء التلقائي للنماذج (واجهة مستخدم شرطية/Get)، يجب إلغاء طلب الحصول على بيانات الاعتماد النشطة لمنع حدوث تعارضات في المتصفّح.
- يُرجى الاتصال بـ "
abortController.abort()" على الرقمAbortControllerالمرفق بطلب الملء التلقائي لـ "navigator.credentials.get()" في انتظار المراجعة قبل الاتصال بـ "navigator.credentials.create()".
2. رصد الميزات
يمكنك تحديد ما إذا كانت ميزة "الإنشاء الشرطي" متاحة من خلال التحقّق من conditionalCreate باستخدام PublicKeyCredential.getClientCapabilities().
const capabilities = await PublicKeyCredential.getClientCapabilities();
if (capabilities.conditionalCreate) {
// Conditional create is available
}
3- إنشاء مفتاح مرور باستخدام ميزة "الإنشاء الشرطي"
- مرِّر
mediation: 'conditional'ضمن خياراتnavigator.credentials.create(). يشير ذلك إلى المتصفّح لمعالجة عملية إنشاء مفتاح المرور في الخلفية أو حسب السياق بدون عرض مربّعات حوار مشروطة مزعجة. - يجب ملء
excludeCredentialsبمعرّفات بيانات اعتماد مفاتيح المرور الحالية للمستخدم لتجنُّب تسجيل مفاتيح مكرّرة.
4. معالجة الأخطاء الصامتة
- يجب تضمين طلب إنشاء مفتاح المرور (
navigator.credentials.create) في كتلة try/catch. يجب رصد الاستثناءات المعتادة الموجّهة للمستخدمين (InvalidStateErrorوNotAllowedErrorوAbortError) وتجاهلها بدون عرض أي واجهة مستخدم تتضمّن رسالة خطأ للمستخدم.
5- التحقّق من تواجد المستخدم من جهة الخادم
- يجب أن تتساهل نقطة نهاية عملية التحقّق من جهة الخادم في شرط "حضور المستخدم" (UP) (
requireUserPresence: false) فقط عند التحقّق من بيانات الاعتماد التي تم إنشاؤها من خلال مشغّل إنشاء مشروط. يجب أن يبقى إعداد "التحقّق الصارم من الحضور" مفعَّلاً لإنشاء المحتوى الفاضح العادي.
6. التعامل مع تعذُّر التحقّق من الخادم بشكل سلس
- إذا نجح
navigator.credentials.create()ولكن عرض استجابة غير صالحة من الخادم عند جلب عملية إثبات الهوية (على سبيل المثال، تعذُّر إثبات صحة التوقيع)، يمكنك استدعاءPublicKeyCredential.signalUnknownCredential()لمنع بقاء بيانات الاعتماد المعزولة في موفّر مفتاح المرور.
مثال على الرمز
// optionsFetch and registerVerifyFetch are app-defined server endpoint requests
import { optionsFetch, registerVerifyFetch } from './api.js';
async function triggerConditionalCreate(loginAbortController) {
const capabilities = await PublicKeyCredential.getClientCapabilities();
if (capabilities.conditionalCreate !== true) {
return; // Platform does not support conditional creation
}
// 1. Abort any active autofill conditional-get controllers to clear the WebAuthn pipeline
loginAbortController.abort();
// 2. Fetch creation options signaling the backend that this is a conditional request
const creationOptionsJSON = await optionsFetch({ conditional: true });
const publicKey = PublicKeyCredential.parseCreationOptionsFromJSON(creationOptionsJSON);
let credential;
try {
// 3. Invoke silent credentials creation prompt
credential = await navigator.credentials.create({
publicKey,
mediation: 'conditional' // Silent background creation mediation
});
} catch (e) {
// 4. Silently swallow common WebAuthn browser exceptions
if (['InvalidStateError', 'NotAllowedError', 'AbortError'].includes(e.name)) {
return;
}
console.error('Unexpected conditional create error:', e);
return;
}
// 5. Server verification step using dedicated Try/Catch block
let encodedResponse = credential.toJSON();
try {
const response = await registerVerifyFetch(encodedResponse);
if (!response.ok) {
// If the server verification fails, clean up using Signal API
if (PublicKeyCredential.signalUnknownCredential) {
await PublicKeyCredential.signalUnknownCredential({
rpId, // RP ID must match the one defined on the server
credentialId: encodedResponse.id
});
}
}
} catch (serverErr) {
console.error('Verification network failure:', serverErr);
if (PublicKeyCredential.signalUnknownCredential) {
await PublicKeyCredential.signalUnknownCredential({
rpId, // RP ID must match the one defined on the server
credentialId: encodedResponse.id
});
}
}
}
الاستراتيجيات الاحتياطية
الاحتياطي لرصد ميزة مفتاح المرور
يجب دائمًا تثبيت "webauthn-polyfills" واستيراده في السياق.
يُرجى العِلم أنّه طالما أنّ PublicKeyCredential متوافق، فإنّ PublicKeyCredential.getClientCapabilities متوافق أيضًا.
import 'webauthn-polyfills';
الاحتياطي لمزامنة Signal API
واجهة WebAuthn Signal API (webauthn-signals) هي تحسين تدريجي يُستخدَم لإبقاء مدراء كلمات المرور متزامنين مع حالة بيانات الاعتماد على الخادم.
- التجربة البديلة: يتم حظرها من خلال
if (PublicKeyCredential.signalUnknownCredential). وإذا لم يكن متوافقًا، يتم تجاوز مزامنة التحقّق في الخلفية بسلاسة بدون ظهور استثناءات في المتصفّح.
Easy JSON Serialization Fallback
يجب دائمًا تثبيت "webauthn-polyfills" واستيراده في السياق.
يُرجى العِلم أنّه طالما أنّ PublicKeyCredential متوافق، يكون PublicKeyCredential.parseCreationOptionsFromJSON وPublicKeyCredential.prototype.toJSON متوافقَين أيضًا.
import 'webauthn-polyfills';