التفويض بلا مصادقة: أمان بلا كلمات مرور
المصادقة والتفويض يحلّان مشكلتين مختلفتين
تبدأ معظم التطبيقات ببوابة. قبل أن يفعل المستخدم أي شيء، عليه أن يثبت هويته: يدخل بريدًا، ويتلقى رمز تحقق، ويختار كلمة مرور، أو يتبع رابطًا سحريًا. هذه الخطوة هي المصادقة، أي عملية تأكيد من يكون الشخص في مقابل سجلٍّ تحتفظ به سلطة مركزية.
أما التفويض فيجيب عن سؤال آخر: ما المسموح لهذا الشخص بفعله؟ تدمج الفرق عادةً الاثنين في تدفّق «تسجيل دخول» واحد، لكنهما يظلّان عمليتين مختلفتين. وفصلهما يكشف فكرة مفيدة.
لا يحتاج الخادم إلى معرفة من هو المستخدم لكي يفرض ما يُسمح له بفعله.
بُني JustCall على هذا الفصل. لا تسجيل، ولا جدول حسابات، ولا كلمة مرور، ولا بيانات شخصية على الخادم. يحمل التفويض النظام كله، بينما المصادقة بمعناها التقليدي غائبة. ثلاث لبنات تجعل ذلك ممكنًا: مفتاح خاص، ومفتاح عام، ودورٌ مفوَّض نسمّيه المفتاح الرئيسي.
كيف تحلّ هوية المفتاح العام محلّ الحسابات
في أول مرة تفتح فيها JustCall، يولّد المتصفح سرًّا محليًّا ولا يرسله أبدًا. ومن هذا السر يشتقّ زوج مفاتيح، ويصبح النصف العام معرّف المستخدم الخاص بك:
// The private key is generated on your device. The server never sees it.
privateKey = crypto.randomUUID();
// The PUBLIC half, encoded as text, becomes your user ID.
userId = await derivePublicUserId(privateKey);
المعرّف هو المفتاح العام نفسه، لا صفٌّ في قاعدة بيانات يشير إليه. وهذا القرار وحده يزيل عدة أعباء تحملها أنظمة الحسابات التقليدية:
- لا خطوة تسجيل. يقبل الخادم الطلبات الموقّعة بمعرّفٍ ما لحظة رؤيته لأول مرة.
- لا بريد ولا رقم هاتف. يُشتق المعرّف من سرٍّ عشوائي على جهازك، لا من أي تفصيل شخصي.
- لا كلمة مرور. لا سرّ مشترك يُخزَّن أو يُجزَّأ أو يُسرَّب، لأن الخادم لا يحتفظ إلا بالمفتاح العام.
- لا تدفّق إعادة تعيين كلمة مرور ولا حشو بيانات اعتماد، إذ لا توجد بيانات اعتماد قابلة لإعادة الاستخدام لمهاجمتها.
أنت لا تكشف هويةً للخادم أبدًا. تُثبت تشفيريًّا أنك تملك المفتاح الخاص الكامن خلف مفتاح عام بعينه، وهذا الإثبات يكفي تفويضًا.
كيف يفوّض الخادم طلبًا
من دون جلسات أو رموز تسجيل دخول، يحمل كل طلب دليله الخاص. يبني العميل حمولة، ويوقّعها بالمفتاح الخاص، ويرسل الاثنين معًا. وعلى الخادم، يختزل التفويض إلى تحقّق توقيعٍ واحد، بلا بحثٍ عن جلسة ولا استعلامٍ من مخزن بيانات اعتماد:
const isValid = await verifyPayload(
request.userId, // the public key = the claimed identity
request.payload, // exactly what was signed
request.signature,
);
if (!isValid) {
return jsonResponse({ message: "invalid signature" }, 401);
}
التوقيع الصالح يجعل الطلب أصيلًا ومُفوَّضًا في عملية واحدة. لا يستطيع مهاجم تزوير طلبٍ لمعرّفٍ لا يملك مفتاحه الخاص، لأنه لا يستطيع إنتاج توقيع مطابق. امتلاك المفتاح الخاص هو السلطة.
المفتاح الرئيسي: ربط الأجهزة دون مشاركة الأسرار
النموذج الذي يحتفظ فيه جهاز واحد بالمفتاح الوحيد ينهار فور إضافة جهاز ثانٍ. إذا احتفظ هاتفك بالمفتاح الوحيد لهويتك، فحاسوبك المحمول غريبٌ عن النظام.
المفتاح الرئيسي يحلّ ذلك. يصبح الجهاز الأول هو الرئيسي ويحتفظ بالسر الأصلي الذي يُشتق منه معرّفك. وكل جهاز إضافي يولّد زوج مفاتيحه المنفصل الخاص. لا يستطيع جهاز جديد التوقيع نيابةً عنك، ولا يُنسخ المفتاح الرئيسي أبدًا بين الأجهزة. يعمل الربط بالتفويض: يوقّع الرئيسي شهادة قصيرة تربط المفتاح العام للجهاز الجديد بمعرّفك.
// Only the master can authorize a new device.
const authorization = {
action: "device-authorization",
userId: identity.userId,
devicePublicKey: newDevice.devicePublicKey, // the new device's PUBLIC key
role: newDevice.role,
createdAt: Date.now(),
};
const signature = await signPayload(identity.privateKey, authorization);
من ذلك الحين، يوقّع الجهاز الجديد طلباته بمفتاحه الخاص، ويتحقق الخادم منها مقابل المفتاح الذي ضمنه الرئيسي. يُصدر الرئيسي بيانات اعتماد دون أن يكشف سرّه قط، تمامًا كما تضمن سلطة إصدار الشهادات موقعًا لا تملك مفتاحه الخاص.
هكذا تحصل على المفردات الكاملة لنظام صلاحيات إنتاجي: الأدوار، والتفويض، والإبطال، وأقل امتياز، معبَّرٌ عنها كلها بالتواقيع. يستطيع الرئيسي إعادة تسمية أي جهاز مرتبط أو إبطاله، والجهاز المُبطَل يفشل في تحقّق توقيعه التالي بينما تُغلق وصلته النشطة.
ماذا يخزّن خادمٌ بلا حسابات
انظر إلى ما تحتويه قاعدة البيانات فعلًا. كل حساب يحتفظ باسم عرضٍ اختاره المستخدم، وصورة رمزية اختيارية، وقائمة بمفاتيح أجهزة عامة. لا شيء غير ذلك. لا بريد ولا أرقام هواتف ولا تجزئات كلمات مرور ولا أسئلة أمان، ولا مفاتيح خاصة، فهي لا تغادر أجهزة المستخدم أبدًا.
تأمّل سيناريو التسريب المعتاد الذي تتسرب فيه قاعدة البيانات بأكملها. يحصل المهاجم على مجموعة من المفاتيح العامة، وهي عامة بحكم التصميم وعديمة الفائدة دون المفاتيح الخاصة المقابلة، إضافةً إلى حفنة من أسماء العرض التي اختارها المستخدمون. لا يستطيع انتحال شخصية أحد، لأن الانتحال يتطلب مفتاحًا خاصًا لم يخزّنه الخادم قط. ولا يستطيع مطابقة المستخدمين بتسريب كلمات مرور، لأنه لا توجد كلمات مرور. ولا يستطيع التصيّد عبر «بريدك»، لأنه لم يُجمع أي بريد قط.
لا يستطيع النظام تسريب بيانات لا يحتفظ بها أصلًا. وأوثق طريقة لحماية المعلومات الشخصية هي عدم جمعها، ونموذج هوية يكون فيه المعرّف مفتاحًا عامًا يجعل ذلك حرفيًّا.
لماذا يقلّل التفويض بلا كلمة مرور خطر التسريب
قارن أسطح الهجوم مباشرةً. على تطبيق البريد وكلمة المرور التقليدي أن يدافع عن قاعدة بيانات اعتماد، وتدفقات إعادة تعيين كلمة المرور، وإرسال رموز البريد والرسائل القصيرة، ورموز الجلسات، وكتلةٍ من البيانات الشخصية المنظَّمة التي صار مسؤولًا عنها. كلٌّ منها مصدر متكرّر للاستيلاء على الحسابات وحوادث التسريب.
نموذج المفتاح العام يدافع عن شيء واحد: أن يحتفظ المستخدم بمفتاحه. وهذه مقايضة حقيقية، إذ لا توجد سلطة مركزية تعيد تعيين مفتاح مفقود. وفي المقابل، يختفي كل بند في القائمة السابقة. ويضيق أثر اختراق الخادم إلى أن يقرأ المهاجم مفاتيح عامة وأسماء عرض، وهي معلومات لم تكن حساسة قط.
تطبيق التفويض بالمفتاح العام في تطبيقك
يتعمّم النمط إلى ما هو أبعد بكثير من تطبيق مكالمات:
- اجعل الهوية زوج مفاتيح واجعل معرّف المستخدم هو المفتاح العام. ولّده على العميل، ولا تنقل النصف الخاص أبدًا، ودَع الحساب ينشأ أول مرة يرى فيها الخادم توقيعًا صالحًا.
- فوِّض بالتحقق من التواقيع بدل فحص الجلسات. كل إجراء يحمل حمولة وتوقيعًا. وقّع على بايتات قانونية ليتفق العميل والخادم على ما وُقِّع بالضبط.
- استخدم مفتاحًا رئيسيًا للتفويض لا للمشاركة. حين يحتاج كيانٌ إلى توسيع الثقة إلى جهاز ثانٍ أو زميل أو عميل واجهة برمجة، دَع المفتاح الجذر يوقّع شهادة محدودة وقابلة للإبطال لمفتاح جديد. السر الجذر لا يتحرك أبدًا.
- خزّن المادة العامة فقط، لتبقى الإجابة عن «ماذا يحدث إن تعرّضنا للاختراق» مملّة.
تستحق بضع قيود الانتباه قبل الإطلاق. تصبح حضانة المفاتيح المشكلة المركزية، لذا تضيف أنظمة الإنتاج خيارات استرداد مثل الاسترداد الاجتماعي، أو نسخة احتياطية مشفّرة اختيارية، أو مفتاح عتادي. وتحتاج الطلبات الموقّعة إلى ختم زمني أو nonce لمنع إعادة التشغيل. ولأنه لا توجد هوية، ينتقل منع البريد المزعج إلى تحديد المعدل أو الدعوات بدل التحقق بالبريد. لا شيء من ذلك يقوّض النموذج. إنها الهموم المعتادة لأي نظام، دون قاعدة بيانات كلمات مرور في المنتصف.
أسئلة شائعة
كيف يمكن لتطبيق أن يفوّض مستخدمًا بلا مصادقة؟ يعامل امتلاك مفتاح خاص بوصفه السلطة. يعمل المفتاح العام معرّفًا للمستخدم، ويُوقَّع كل إجراء بالمفتاح الخاص المقابل، ويتحقق الخادم من ذلك التوقيع مقابل المفتاح العام. يُثبت المستخدم أنه مسموح له بالتصرف دون أن يثبت هويته لنظام حسابات مركزي.
هل النموذج بلا حساب أقل أمانًا من البريد وكلمة المرور؟ في معظم النواحي هو أكثر أمانًا. لا قاعدة كلمات مرور لتُسرَّب، ولا تدفق إعادة تعيين لإساءة استخدامه، ولا بيانات شخصية لتُفقَد. المقايضة هي حضانة المفتاح: إن فقد المستخدم مفتاحه دون نسخة احتياطية، فلا سلطة مركزية تسترد الحساب.
ما الفرق بين المصادقة والتفويض؟ المصادقة تثبت من أنت. والتفويض يثبت ما المسموح لك بفعله. تجمع معظم الأنظمة بينهما، لكن زوج المفاتيح يتيح الثاني دون الأول.
ماذا يحدث إن اختُرقت خوادم JustCall؟ سيجد المهاجم مفاتيح عامة وأسماء عرض. المفاتيح العامة مقصودٌ بها أن تكون عامة وهي عديمة الفائدة دون المفاتيح الخاصة التي لا تغادر أجهزتك أبدًا. لا كلمات مرور ولا بريد ولا أرقام هواتف لتُسرَق.
هل أستطيع استخدام أكثر من جهاز بلا حساب؟ نعم. يعمل الجهاز الأول رئيسيًا ويوقّع شهادة تربط المفتاح العام لكل جهاز جديد بمعرّفك. السر الرئيسي لا يُنسخ أبدًا، ويستطيع الرئيسي إبطال أي جهاز في أي وقت.