← All posts

أخبرنا مزوّد هوية بمن تكون، فصدّقناه

Authagonal·July 6, 2026
authsecurityssosamloidcfederation

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

إليك المشهد. يستطيع مستأجر على منصّتنا أن يهيّئ اتصالات متّحدة: SAML نحو IdP الخاص بشركته، وOIDC نحو آخر. يسجّل مستخدم دخوله عبر أحد تلك الاتصالات، فيردّ IdP بتأكيد، ويتعيّن على خادمنا أن يجيب عن سؤال واحد: أيُّ حساب محلّي هذا؟ أخطئ في تلك المطابقة فيكون لديك إمّا غريب محبوس خارج حسابه هو، أو ما هو أسوأ بكثير: غريب يدلف إلى حساب شخص آخر.

كان مفتاح الربط بريدًا إلكترونيًا، والبريد الإلكتروني ليس سوى ادّعاء

أجاب رمزنا عن «أيُّ حساب هذا» بالطريقة البديهية. كان التأكيد يحمل بريدًا إلكترونيًا، فبحثنا عن المستخدم به: FindByEmailAsync(assertedEmail). وإن وُجد حساب مطابق، حُلّت هوية المستخدم المتّحد العائد إليه وسُجّل دخوله. نظيف وبسيط، وهو بالضبط كيف تُكتب كثير من تكاملات SSO.

المشكلة هي ما يكونه ذلك البريد الإلكتروني فعلًا. إنه ليس حقيقة أثبتها IdP. إنه سلسلة نصّية داخل تأكيد، والتأكيد ليس جديرًا بالثقة إلا بقدر ما يكون الاتصال الذي جاء عبره جديرًا بها. في عالم متعدّد المستأجرين لا تتحكّم في كل اتصال. وأيُّ شخص يستطيع أن يقيم اتصالًا (IdP خاص به على SAML، أو مزوّد OIDC خاص به) يستطيع أن يضع أيّ سلسلة يشاء في حقل البريد الإلكتروني. فاتصال لا تثق به يدّعي email = [email protected]، فيعثر بحثنا على حساب الرئيس التنفيذي الحقيقي، فيصير المهاجم مسجَّل الدخول باسمه. لا كلمة مرور، ولا تصيّد، ولا خلل في التعمية. كان التوقيع على التأكيد صحيحًا تمامًا. غاية ما فعله أنه ضمن ادّعاءً ما كان ينبغي لنا قطّ أن نعامله كهويّة.

أمّا المقلق فهو أن كل جزء على حدة كان يعمل. صادق IdP على مستخدمه هو بشكل صحيح. وتحقّق التوقيع. وكان الحساب موجودًا. لم يكن الاستيلاء فشلًا في أيّ فحص؛ بل كان استعمالًا للحقل الخطأ كمفتاح.

لماذا ليس مزيد التحقّق هو الإصلاح

الردّ المغري هو التحقّق من البريد الإلكتروني بصرامة أشدّ. اشترط email_verified. افحص النطاق. أضف قاعدة. لكن لاحظ شكل الفخّ: المهاجم يتحكّم في التأكيد، فأيُّ خاصّية تقرؤها من التأكيد هي خاصّية يستطيع المهاجم ضبطها. أن تطلب email_verified = true من اتصال يملكه المهاجم نفسه أشبه بأن تأتمن الذئب على الحظيرة. لا تستطيع أن تتحقّق طريقًا للخروج من الوثوق بالمصدر الخطأ.

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

كان الإصلاح هو تغيير المفتاح، لا إضافة فحوصات

الإصلاح الحقيقي كان التوقّف نهائيًا عن الربط بالبريد الإلكتروني والربط بالشيء الوحيد الذي لا يستطيع اتصال أن يزوّره عن مزوّد لا يملكه: الزوج (provider, sub). الـ sub هو معرّف الموضوع الذي يصدره المزوّد لذلك المستخدم، محصورًا في نطاق ذلك المزوّد. تُحلّ هوية المستخدم العائد بالبحث عن الهوية المحلّية التي رُبطت سابقًا بـ (provider, sub) الخاص بـهذا الاتصال. اتصال المهاجم له معرّف مزوّد خاص به؛ يستطيع أن يسكّ أيّ sub يشاء داخل فضاء أسمائه هو، لكنه لا يستطيع أن ينتج (provider, sub) العائد لاتصال شخص آخر. فضاء الأسماء هو الخندق الحصين.

عندها يهبط البريد الإلكتروني إلى الدور الذي كان ينبغي له دائمًا أن يؤدّيه: قرينة للـربط، لا للـحلّ أبدًا، وفقط حين يكون مضمونًا. لا نطابق بريدًا إلكترونيًا مُدّعى بحساب قائم إلا حين يكون البريد متحقّقًا منه عبر مصدر نثق به فعلًا لذلك النطاق: email_verified صادر عن اتصال نطاقه ضمن AllowedDomains الخاصة بالمستأجر. وخارج ذلك، تحصل الهوية المتّحدة الجديدة على حسابها هي، لا حساب شخص آخر.

الدرس، مُجرَّدًا

حين تتّحد بهوية، افصل بين سؤالين تُغرى بدمجهما. «هل صادق هذا المزوّد على هذا المستخدم؟» يجيب عنه التوقيع. «من هذا المستخدم في نظامي؟» لا بدّ أن يجيب عنه مفتاح لا يستطيع الطرف المؤكِّد أن يزوّره عبر الحدود، أي subject خاص بكل مزوّد، لا سمة عالمية كالبريد الإلكتروني. عامِل كل حقل في تأكيد على أنه تحت سيطرة المهاجم، إلا أن يكون المصدر المحدّد لذلك الحقل مصدرًا تثق به لذلك الادّعاء المحدّد بعينه. البريد الإلكتروني هو الحقل الذي يمدّ الناس أيديهم إليه أولًا لأنه إنسانيّ ويبدو فريدًا. وهو بالضبط الحقل الخطأ.

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

أن تتّحد بالهوية بأمان يتلخّص في الربط عبر مفتاح لا يستطيع الطرف المؤكِّد أن يزوّره، وأن تخطئ في ذلك يعني استيلاءً على حساب يجتاز كل اختبار. يحلّ Authagonal هوية المستخدمين المتّحدين عبر الـ subject الخاص بكل مزوّد، لا عبر البريد الإلكتروني الوارد في التأكيد أبدًا.