خمس كلمات مرور خاطئة تقفل الحساب. كان الفحص صحيحاً والعتبة صحيحة، ومع ذلك كان بإمكانك إرسال عشرة آلاف كلمة مرور خاطئة دون أن تُطلق القفل أبداً، ما دمت ترسلها دفعة واحدة. كان العدّاد عملية قراءة وتعديل وكتابة بلا حماية، فكانت المحاولات المتزامنة تدهس زيادات بعضها بعضاً ولا يكاد يرتفع. الإصلاح هو كيف تبني عدّاداً ذرّياً على مخزن مفتاح وقيمة لا يملك عملية زيادة، وإعادة التأطير التي رافقته: افترض أن أحدهم يعدّ بالتوازي.
صار الدخول الموحّد معيارًا مستقرًا منذ أكثر من عشرين عامًا، ومع ذلك يظل SAML البند الذي يعطّل الصفقة أو يدفعك إلى الاتصال بفريق المبيعات. كيف تحوّلت مصادقة المؤسسات إلى ترقية مدفوعة، ومن بنى ذلك العالم ومن حذّرنا منه، وما اتساع الخندق الدفاعي حقًا ومِمَّ يتكوّن، والقوة الوحيدة التي تستنزف نصفه بهدوء.
المراقبة هي الشيفرة التي لا تعمل إلا أثناء الكارثة، اللحظة الوحيدة التي لا تحتمل أن تجدها معطلة فيها. لذلك بنينا منظومة اختبار تُطلق إشارة حقيقية لكل قاعدة تنبيه، وترفض أن تنجح حتى يصل الإشعار فعليًا إلى مُرحِّل التقاط. كشف أول تشغيل أن تنبيه معدل الأخطاء الرئيسي لدينا ميت تمامًا، ثم كشف ما هو أسوأ: إعداد احتفاظ فرض بصمت انتهاء صلاحية فوريًا على سجلاتنا، فصارت فئة كاملة من التنبيهات تُقيَّم فوق لا شيء بينما بدا استيعاب البيانات سليمًا.
مئة ميغابايت من لقطات شاشة التوثيق انتقلت إلى Cloudflare R2، خلف قاعدة CDN يشتقّها التطبيق وقت التشغيل من اسم مضيفه. في المتصفح عمل كل شيء، لكنه لم يغيّر شيئًا في حركة الخادم الأصلي، لأن الصفحات التي يراها الزاحف تُصيَّر مسبقًا على 127.0.0.1 حيث لا يدل اسم المضيف على شيء. الحل هو عنصر نائب يحمله HTML خارج البناء وتملؤه الحافة لكل طلب، وسبب اضطراره للعمل هكذا هو نظام ملفات للقراءة فقط.
كان التزويد الآني (Just-in-time) مفعّلًا افتراضيًا، لذا كان بإمكان أي موفّر هوية موحّد إنشاء حسابات داخل مستأجر أحد العملاء لمجرد أن يؤكّد أن شخصًا ما موجود. إيقاف هذا الإعداد الافتراضي تغيير من كلمة واحدة. أما إيقافه دون أن يغيّر بصمت سلوك كل اتصال مخزَّن بالفعل، ولم يكتب أي منها العمود قط، فهو المشكلة الحقيقية، والحيلة التي حلّتها تفسّر أيضًا لماذا يُعدّ الإعداد الافتراضي جزءًا من واجهة الـ API.
يُخرِج نمط backend-for-frontend رموز OAuth من المتصفح فلا يبقى بيده سوى كوكي مبهم. وخدمة مستأجرين كثيرين من BFF واحد هي في معظمها مسألة توصيلات، إلى أن يصل تسجيل الخروج عبر القناة الخلفية: طلب POST من خادم إلى خادم بلا كوكي ولا جلسة ولا متصفح، حيث الشيء الوحيد الذي يحدد المستأجر هو ادعاء داخل رمز لم تتحقق منه بعد.
أضفنا إلى عنقود Kubernetes لدينا admission webhook يتحقق من التواقيع، حتى لا تعمل أبدًا أي صورة غير موقَّعة. بعد ساعات، كان لدى Deployment واحد 2242 من ReplicaSet، واحد جديد كل ثلاث ثوانٍ، ولا pod متاح واحد. أظهرت سجلات الـ webhook أنه يقبل كل طلب على الإطلاق. جاء الضرر من الكلمة الوحيدة في "mutating admission webhook" التي كنا قد توقفنا عن قراءتها.
كان المستخدم العائد يشاهد كلمة «جارٍ التحميل…» لعشر ثوانٍ بالضبط قبل أن تظهر صفحة تسجيل الدخول، في كل مرة. كان الرقم المستدير هو الدليل: فتحت مكتبة الدخول الموحّد (SSO) لدينا إطار iframe مخفيًّا للتجديد الصامت موجّهًا نحو مضيف مصادقة يقدّم X-Frame-Options: DENY وframe-ancestors 'none'، فلم يُحمَّل الإطار قطّ، ولم يُخطئ قطّ، وانتظرت المكتبة حتى انقضاء مهلتها الزمنية كاملةً. دفاع مكافحة سرقة النقر وتجديد OIDC الصامت، وكلاهما صحيح، علِقا في الوصلة بينهما.
قمنا بتشفير كل عناوين البريد الإلكتروني أثناء التخزين، فتوقف مربع البحث في لوحة الإدارة بهدوء عن الإكمال التلقائي: لا خطأ، ولا سطر في السجلات. يعيد الفهرس الأعمى (blind index) إمكانية البحث بالمطابقة التامة فوق النص المشفر، لكن وظيفة HMAC الأساسية هي تدمير الترتيب الذي يحتاجه البحث بالبادئة. إليكم التصميم الذي أعاد البحث الاستباقي (فهرسة كل بادئة كقيمة مستقلة)، والفخاخ الثلاثة التي علمتنا أن التشفير القابل للبحث مشكلة أنظمة، لا مشكلة تشفير.
نقلنا توقيع JWT من RS256 إلى ES256، وكان كل رمز نصدره صالحًا تشفيريًا ومرفوضًا في آن واحد. ثلاث مرات، ولثلاثة أسباب مختلفة: DER حيث يريد JWS تنسيق R‖S الخام، وحشو أعداد صحيحة يفشل في رمز واحد من كل 128، ولهجة base64 تغيّرت من تحت أقدامنا. إليك كيف تقرأ البايتات المشوهة وتسمّي الطبقة المذنبة من طول التوقيع وحده.
المستندان اللذان تقرؤهما أي خدمة للتحقق من أحد رموز JWT لدينا — مستند الاكتشاف (discovery) وJWKS — هما أكثر ما نقدّمه طلباً وأقلّه سرّيةً، وكانت كل عملية جلب تعود طوال الطريق إلى الأصل (origin). كان تخزينهما مؤقتاً على Cloudflare هو الجزء السهل. أما الجزء الصعب فهو أن ذاكرة مؤقتة قديمة للمفاتيح العامة يجب ألّا ترفض أبداً رمزاً صالحاً، وإليك ترتيبَ العمليات الآمن للتدوير الذي يجعل JWKS المُخزَّن مؤقتاً بقوة آمناً.
تبلغ تكلفة باقة LITE من Duende مبلغ $5,750/yr، لكنها لا تتيح سوى 2 من تطبيقات العملاء ولا تدعم SAML على الإطلاق. وفي اللحظة التي تحتاج فيها إلى SSO للمؤسسات أو إلى تطبيق ثالث، تجد نفسك أمام باقة STANDARD بسعر $12,500. نظرة على ما يكلّفه Duende فعلياً لمنتج حقيقي، وعلى ضريبة عدد التطبيقات التي لا يحذّرك منها أحد.
مفتاح خاص واحد يوقّع كل رمز يُصدره خادم المصادقة لدينا، وقد انتقل مرتين في حياته: وُلد داخل العملية، ثم نُفي إلى خزنة لا يستطيع مغادرتها، ثم تناسخ ليصبح نوعاً من المفاتيح أصغر وأسرع تماماً. حدث كل انتقال على جهة إصدار حيّة والرموز في طريقها. إليك ما يتطلبه فعلياً تغييرُ الحيازة والخوارزمية، والتراجعُ الصامت الذي تسلّل مع تغييرة (commit) موصوفة بأنها «أكثر أماناً».
تحقّق مزوّد الخدمة لديك من توقيع التأكيد، وثبّت الشهادة، وسجّل دخول المستخدم. كل الفحوص نجحت. ومع ذلك أعدتُ تشغيل عملية تسجيل دخول التقطتها قبل ساعة. الحيلة لم تكن في كسر التوقيع، بل في حذف حقلٍ لم يشمله التوقيع قط.
طلبنا العامل الثاني في صفحة تسجيل الدخول ولم نعد التحقق منه عند الـ endpoint الخاص بالـ token. وهكذا مرّت كلمة مرور صحيحة مع URL عودة معدّل يدويًا مباشرة متجاوزة MFA. الإصلاح، والقاعدة التي علّمنا إياها: MFA خاصية للجلسة التي تُصدرها، وليس خطوة في شاشة تسجيل الدخول.
SCIM واجهة CRUD قياسية أهم أفعالها هو الفعل الذي يعطّل حساب الموظف المغادر. يسعّرها الموردون بـ 125 دولارًا شهريًا لكل اتصال، أو يضعونها في الباقة المؤسسية إلى جانب SSO. إليك ما يكلفه اتصال SCIM فعلًا لتقديمه، ولماذا يعدّ فرض رسوم على إلغاء التزويد فرضًا لرسوم على الأمان.
لا توجد في Azure Table Storage وDynamoDB علامات حذف، فالصف المحذوف يتلاشى ببساطة، ما يعني أن نسختك الاحتياطية التزايدية لا ترى الحذف إطلاقًا. استعد تلك النسخة وسيعود المستخدم الذي أنهيت حسابه، ومعه كلمة المرور التي تخلصت منها بالتدوير. إليك لماذا يجب أن تكون عمليات الحذف عنصرًا من الدرجة الأولى، والجدول الوحيد الذي يجعلها كذلك.
كان الـ rate limiter وعدّاد قفل الحسابات لدينا يعتمدان على عنوان IP الخاص بالعميل. خلف nginx كان ذلك العنوان يأتي من ترويسة يستطيع العميل ضبطها بنفسه، فكفت ترويسة متغيرة واحدة لمنح كل طلب عنوان IP جديداً وانهارت كل آليات التحكم لكل IP. التزوير بسطر واحد، والإصلاح الذي هو أعقد مما يبدو على Kubernetes.
يمنحك Azure Table Storage مفتاح تقسيم (partition key) ومفتاح صف (row key) ولا شيء آخر تقريباً. لا عمليات ربط (joins)، ولا فهارس ثانوية تستحق الاسم، ولا عامل زيادة. ومع ذلك نُشغّل عليه نظام مصادقة متعدد المستأجرين. الأنماط التي تجعله يعمل، وما الذي تتنازل عنه مقارنةً بـ SQL.
نقطة نهاية لإعادة تعيين كلمة المرور غير مُصادَق عليها وبلا تحديد للمعدل لكل بريد إلكتروني ليست مشكلتك وحدك. صوّبها نحو صندوق وارد شخص آخر وتكون قد حوّلت نموذج إعادة التعيين الخاص به إلى مدفع بريد مزعج، محسوب على سمعة المُرسِل لديك. والحل، دون تسريب أي البُرد الإلكترونية لها حسابات.
معظم مزوّدي المصادقة يسيّجون SSO وSCIM وMFA وسجلات التدقيق خلف خطة Enterprise. نحن وضعناها كلها في خطة الـ $0. إليك اقتصاديات الوحدة التي تجعل منح الميزات مجانًا أمرًا قابلًا للاستمرار: الجدار لم يكن يومًا هو الميزات، بل المستخدمون النشطون والدعم.
الدخول الموحّد يعني الوثوق بمزوّد الهوية. وثقنا به في أمر واحد زائد عن الحدّ: كنّا نحلّ هوية المستخدمين المتّحدين العائدين بناءً على البريد الإلكتروني الوارد في التأكيد، فصار بإمكان أي اتصال أن يدّعي عنوان شخص آخر ويهبط على حسابه. لم يكن الإصلاح مزيدًا من التحقّق، بل تغيير مفتاح ربط الهوية من البريد الإلكتروني إلى subject خاص بكل مزوّد لا يستطيع الطرف المؤكِّد تزويره.
وعدتنا Azure Container Apps بأن نتوقف عن الدفع مقابل عنقود مصادقة خامل. حسبنا تكلفة الترحيل ثم ألغيناه، لا بسبب السعر ولا البدايات الباردة، بل لأن النموذج اللاخادمي يفتقد الرقم الوحيد الذي تحتاجه فعلاً منصة مصادقة خلفية تعتمد انتخاب قائد.
«ضريبة الميزة» على هيئة فاتورة حقيقية. ثلاثة سيناريوهات للمشتري (أول صفقة enterprise، حفنة من العملاء، SSO كشرط أساسي) محسوبة مقابل الأسعار المعلنة لكل مزوّد. إضافة إلى الرسم الإضافي الصامت الذي لا يحذّرك منه أحد: نفاد عملاء OAuth في منتصف التكامل.
ظلّت مجموعة من ثلاث نسخ متماثلة تختلف مع نفسها باستمرار. كان السبب في شيفرتنا نحن: إذ احتوى روتين اكتشاف الأقران على كتلة catch تُعطّل الاكتشاف عند فشل multicast، وعلى Kubernetes المُدار يفشل multicast دائمًا. هذه قصة سبب حذفنا gossip بالكامل وانتخابنا قائدًا عبر blob lease بدلًا منه، وسبب تفوّق قائمة عضوية يمكنك فتحها في Storage Explorer على قائمة عضوية مضطر إلى استنتاجها.
تسجيل الدخول عطلة نهاية أسبوع. أما الفاتورة فتصل بعد ذلك: التحقق من التوقيع، وإلغاء التزويد عبر SCIM، وMFA، وسجلات التدقيق، وتدوير المفاتيح، والمسؤولية عن الاختراقات، والمناوبة على نظام من المستوى صفر. مقارنة صادقة بين البناء والشراء، بما في ذلك متى يكون البناء هو الصواب.
OIDC أم SAML؟ نادراً ما يكون لك حق الاختيار. ما هو كل بروتوكول، ومتى يتفوق كل منهما، ومزالق توقيع XML التي تجعل بناء SAML يدوياً أمراً خطيراً، ولماذا ينتهي أي منتج B2B إلى الحاجة لكليهما.
نظام الدعم من Authagonal: رسائل فورية بلا إعادة تحميل، وترجمة بالذكاء الاصطناعي شفافة في الاتجاهين، مثبَّتة منذ أول رسالة للعميل، ومحادثة تبقى مترجمة بالكامل حتى عبر البريد الإلكتروني. بسيط وأنيق وقادرٌ فعلاً.
اثنان من مستأجرينا كانا في الخفاء المستأجر نفسه: قاعدة بيانات واحدة، ومفتاح توقيع رموز واحد، واسمان مختلفان. كان السبب دالة مساعدة من سطر واحد تُنظّف الـ slugs عبر إزالة الشرطات، فتُحوّل مُعرّفًا فريدًا إلى مُعرّف غير فريد. إليك كيف تحوّل تحويل نصي فاقد للبيانات إلى استيلاء عابر بين المستأجرين، ولماذا اكتشفناه قبل أن تكتشفه أنت.
نحن نبيع المصادقة، ولذلك فإن أهم اختبار لدينا هو الاختبار الذي يتحول إلى عميل: تشغيلة واحدة من Playwright تسجّل مستأجراً جديداً، وتضبط كل ميزة، وتوجّه تطبيقاً حقيقياً إليه، وتسجّل دخول مستخدم حقيقي بالمطالبات الصحيحة، ثم تأخذ نسخة احتياطية وتستعيدها وتحذف نفسها. كيف منح الاختبار الشامل من البداية إلى النهاية الثقة في إطلاقنا.
تتم المصادقة على وحدة تحكم موظفينا من خلال Authagonal نفسه، مع تكفّل Entra SSO وSCIM بعملية التزويد. أن تكون عميل نفسك يكشف الحالات الحدّية التي لا تفكّر أي مجموعة اختبارات في كتابتها. وهذه هي الحالات التي كان لها أثر فعلي.
حالة Terraform لديك هي خريطة كاملة لسحابتك إضافة إلى كومة من الأسرار، وهي تعيش بشكل افتراضي خلف نقطة نهاية عامة. إليك كيف أقمنا الحالة البعيدة من الصفر، ووضعناها خلف نقطة نهاية خاصة، ووصلنا إليها عبر موصل zero-trust بدلًا من دفع ضريبة بوابة VPN، من دون أن نحبس أنفسنا في الخارج قط.
عبارة "الجميع يعيد تعيين كلمة المرور" هي خيار يخص عملية الترحيل، وليست قانوناً من قوانين الفيزياء. إليك كيف تنقل دوال التجزئة الحالية لكلمات مرور مستخدميك عبر انتقال مزود الهوية، بحيث يكون التحول غير محسوس، والحالة الوحيدة التي يتعذّر فيها ذلك فعلاً.
تقيس صناعة المصادقة الإذن، لا التكلفة. فهي تحجب SSO وMFA والتزويد التلقائي خلف باقات ورسوم لكل اتصال، مقابل ميزات لا تكلف تقديمها شيئًا يُذكر. وإليك الفارق الذي تأمل صفحات التسعير ألا تستوعبه أبدًا.
الانتقال من Duende IdentityServer ذاتية الاستضافة إلى مصادقة مُدارة: ما الذي يُرحَّل فعليًا من إعدادات SQL ومن ASP.NET Identity، والتكلفة التشغيلية التي تتوقف عن تحمّلها.
نظرة عملية على ما تتطلبه عملية ترحيل Auth0 فعلاً: ما هو سهل، وما هو شائك، والشيء الوحيد الذي لن يمنحك إياه Auth0 حقاً.