المصادقة هي الحارس الواقف على باب تطبيقك. في كل مرة يقوم فيها شخص ما بالتسجيل أو تسجيل الدخول، يجب على نظامك أن يقرر ما إذا كان هو بالفعل الشخص الذي يدعي أنه هو. إذا أخطأت في ذلك، فلن تقتصر المشكلة على تصحيح خطأ في تسجيل الدخول فحسب، بل ستخاطر بخروج بيانات مستخدمين حقيقية مباشرة من الباب. يتطلب القيام بذلك بشكل صحيح أداتين موثوقتين: Bcrypt لحماية كلمات المرور أثناء تخزينها، و JSON Web Tokens للتحقق من الهوية أثناء تنقل المستخدم داخل تطبيقك.
لماذا يفشل تخزين النصوص المجردة (Plaintext)
إذا كنت ستخرج بقاعدة واحدة فقط من هذا المقال، فاجعلها هذه: لا تقم أبدًا بتخزين كلمات المرور كنصوص مجردة (plaintext) في قاعدة بياناتك. لا يهم ما إذا كانت قاعدة بياناتك محمية بجدار حماية أو إذا كنت تثق في كل مهندس في الفريق. إن كتابة كلمات المرور في الجداول بصيغتها الخام يشبه ترك مفاتيح المنزل تحت ممسحة الأرجل. في اللحظة التي يتمكن فيها شخص ما من الوصول إلى قاعدة البيانات تلك — من خلال واجهة برمجة تطبيقات (API) سيئة التكوين، أو نسخة احتياطية مسربة، أو هجوم حقن (injection attack) — يتم كشف كل بيانات الاعتماد على الفور.
تتضاعف الأضرار لأن الناس يعيدون استخدام كلمات المرور. يمكن لخرق واحد أن يعرض للخطر ليس تطبيقك فحسب، بل أيضًا بريد المستخدم الإلكتروني، وحساباته المصرفية، وحسابات التواصل الاجتماعي الخاصة به. لهذا السبب نقوم بعملية التجزئة (Hashing) لكلمات المرور. تقوم التجزئة بتحويل كلمة المرور إلى سلسلة نصية مشفرة لا تشبه الأصل بأي شكل واضح. هذه العملية أحادية الاتجاه وغير قابلة للعكس؛ فلا يمكنك سكب "حمض رياضي" على الهاش لإذابته وإعادته إلى كلمة المرور التي أنشأته.
تجزئة كلمات المرور باستخدام Bcrypt
تعد Bcrypt دالة تجزئة (hashing function) صُممت خصيصًا لكلمات المرور. فهي تأخذ السلسلة النصية المجردة، وتمررها عبر شفرة Blowfish، وتعيد نتيجة تشبه شيئًا مثل $2b$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy. يخبرك هذا البادئة بالخوارزمية وعامل التكلفة (cost factor). أما الجزء الطويل في النهاية فهو مزيج من الملح (salt) والهاش نفسه.
الملح (salt) هو بيانات عشوائية يتم دمجها في كلمة المرور قبل بدء عملية التجزئة. ولأن الملح فريد لكل مستخدم، فإن شخصين يختاران "password123" سينتهي بهما الأمر إلى الحصول على هاشات مختلفة تمامًا في قاعدة بياناتك. هذا الاختلاف البسيط يهزم جداول قوس قزح (rainbow tables) — وهي قواميس محسوبة مسبقًا من الهاشات لكلمات المرور الشائعة — لأن المهاجمين سيحتاجون إلى إعادة إنشاء الجدول بالكامل لكل ملح فريد.
تتميز Bcrypt أيضًا بأنها بطيئة عن قصد. يمكن للأجهزة الحديثة تخمين المليارات من الهاشات في الثانية باستخدام خوارزميات سريعة مثل SHA-256، لكن Bcrypt تتعمد التباطؤ. فهي تقوم بتشغيل عملية التجزئة عدة مرات، ويتم التحكم في ذلك من خلال عامل التكلفة الذي يمكنك رفعه مع زيادة سرعة أجهزة الكمبيوتر. هذا البطء يعاقب أي شخص يحاول استخدام هجوم القوة الغاشمة (brute-force) لاختراق قاعدة بيانات مسروقة. المستخدم الشرعي الذي ينتظر مائتي مللي ثانية إضافية أثناء تسجيل الدخول لن يلاحظ ذلك، أما المهاجم الذي يحاول اختبار ملايين التخمينات فسيلاحظ ذلك بالتأكيد.
كيف تعمل رموز JSON Web Tokens
بينما تتولى Bcrypt حماية الباب الأمامي، تتولى JWT مهمة "تصريح المرور" في الممرات. رمز JSON Web Token هو سلسلة نصية مدمجة وآمنة للاستخدام في الروابط (URL-safe) تثبت أن المستخدم قد تم التحقق من هويته بالفعل. فكر فيه كبطاقة هوية رقمية يصدرها الخادم ويحملها العميل معه.
يحتوي JWT على ثلاثة أجزاء تفصل بينها نقاط: الترويسة (header)، والحمولة (payload)، والتوقيع (signature). تحدد الترويسة نوع الرمز وخوارزمية التوقيع. وتحمل الحمولة الادعاءات (claims) — وهي معلومات حول المستخدم والرمز نفسه — مثل معرف المستخدم، واسم المستخدم، وطابع زمني لانتهاء الصلاحية. أما التوقيع فهو الختم التشفيري؛ حيث يقوم الخادم بإنشائه عن طريق ترميز الترويسة والحمولة، ثم تمريرهما عبر مفتاح سري. إذا عبث أي شخص بالحمولة، فلن يتطابق التوقيع بعد ذلك، وسيرفض الخادم الرمز تمامًا.
