Bugsy
كل الشروحات

Bugsy يشرح

OAuth وJWT ومفاتيح المرور: ما الفرق بينها؟

ثلاث كلمات تختلط علينا لأنها تظهر في تسجيل الدخول نفسه: OAuth يُعير التطبيق صلاحيات محدودة، وJWT ورقة موقَّعة يستطيع أي أحد قراءتها، ومفتاح المرور يأخذ مكان كلمة مرورك، وهو مفتاح لا يستطيع التصيّد (phishing) سرقته.

9 دقائق لعبة واحدة

  • المصادقة
  • الأمان
  • الويب

تضغط Sign in with Google في تطبيق جديد، وبعد لحظة تجد نفسك في الداخل. فهل عرف ذلك التطبيق للتو كلمة مرور حسابك في Google؟

لا، والسبب فكرة تصميم ذكية وبسيطة. في هذه الصفحة ستتعرّف إلى ثلاث كلمات تظهر كثيرًا في تسجيل الدخول نفسه: OAuth وJWT ومفاتيح المرور (passkeys). كل واحدة منها تحلّ مشكلة مختلفة، ولهذا بالضبط تعمل معًا بشكل جيد.

من أنت، وماذا يحق لك أن تفعل؟

في كل تسجيل دخول يختبئ سؤالان. المصادقة (authentication) تسأل «من أنت؟» وتتحقق من أنك فعلًا ذلك الشخص. والتفويض (authorization) يسأل «ماذا يحق لك أن تفعل؟» ويقرر أي الأبواب تُفتح لك، أي ما لك من صلاحيات.

تخيّل فندقًا. في مكتب الاستقبال تُظهر هويتك: هذه هي المصادقة. ثم تتسلّم بطاقة مفتاح تفتح غرفتك والنادي الرياضي، لا غرف النزلاء الآخرين: هذا هو التفويض. والبطاقة لا تعرف اسمك، بل تعرف فقط ما يحق لها أن تفتحه، وتتوقف عن العمل يوم مغادرتك.

OAuth: تُعير مفتاحًا، لا كلمة مرورك

يتعلّق OAuth 2.0 بالتفويض، وتحديدًا بـالإنابة (delegation): أن تسمح لتطبيق ما بأداء مهمة محدودة نيابةً عنك لدى خدمة أخرى، كأن يقرأ تطبيق وصفات طعام تقويمك في Google، دون أن تعطيه كلمة مرورك أبدًا.

هكذا يجري الأمر عادةً. يرسلك التطبيق إلى Google. فتسجّل دخولك لدى Google، على صفحة Google نفسها، ويسألك Google هل تسمح لهذا التطبيق برؤية تقويمك. فإن وافقت، أعادك Google إلى التطبيق ومعك رمز تفويض (authorization code) قصير العمر يُستخدم مرة واحدة.

ثم يبادل خادم التطبيق رمز التفويض هذا لدى Google بـرمز وصول (access token): وهو بطاقة المفتاح. ومن تلك اللحظة يُظهر التطبيق رمز الوصول في كل مرة يستدعي فيها واجهة Google البرمجية (API). لا يرى التطبيق كلمة مرورك أبدًا، وتستطيع سحب المفتاح منه متى شئت من إعدادات حسابك في Google.

اختبار سريع

النطاقات، وكيف صار OAuth وسيلةً لتسجيل الدخول

رمز الوصول ليس مفتاحًا لكل شيء. فحين يرسلك التطبيق إلى Google، يذكر النطاقات (scopes): ما يريده بالضبط، كقراءة تقويمك أو رؤية بريدك الإلكتروني. ويعرض Google هذه القائمة في شاشة الموافقة، ولا يعمل رمز الوصول إلا فيما وافقت عليه.

لاحظ ما لا يقوله OAuth وحده: من أنت. فرمز الوصول موجّه إلى واجهة Google البرمجية، لا ليقرأه التطبيق: وهو ليس وعدًا بشأن من سجّل دخوله. وOpenID Connect (OIDC) طبقة رقيقة فوق OAuth تسدّ هذه الثغرة: يطلب التطبيق أيضًا النطاق openid، فيتسلّم رمز هوية (ID token) إلى جانب رمز الوصول. ورمز الهوية شهادة موقَّعة من Google تقول: «هذا هو المستخدم 42، وقد سجّل دخوله قبل لحظات».

JWT: صيغة، لا بروتوكول

OAuth بروتوكول (protocol): سلسلة خطوات تتبعها التطبيقات والخوادم. أما JWT (اختصار JSON Web Token، ويُلفظ غالبًا «جوت») فشيء آخر: صيغة (format) لكتابة الرموز (tokens). ورموز الهوية في OIDC هي دائمًا JWT، وكثير من رموز الوصول كذلك، مع أن OAuth لا يشترط ذلك.

يتكوّن JWT من ثلاثة أجزاء تفصل بينها نقاط: header.payload.signature. تقول الترويسة (header) كيف وُقِّع الرمز، وتحمل الحمولة (payload) الادعاءات (claims)، أي حقائق عن المستخدم وعن الرمز نفسه، ويحمي التوقيع (signature) الاثنين معًا. وهكذا يبدو الجزآن الأولان بعد فكّ ترميزهما:

{ "alg": "HS256", "typ": "JWT" }.{  "sub": "42",  "name": "Sam",  "role": "user",  "iat": 1767225600,  "exp": 1767226500}.base64url(HMAC-SHA256(base64url(header) + "." + base64url(payload), secret))

sub (subject) هو من يخصّه الرمز، وiat وقت إصداره، وexp وقت انتهاء صلاحيته، وكلاهما بالثواني منذ عام 1970. هنا تأتي exp بعد iat بـ 900 ثانية: أي أن هذا الرمز يعيش 15 دقيقة. ويبيّن السطر الأخير كيف يُصنع التوقيع: HMAC على الجزأين المرمَّزين بينهما نقطة، ثم يُرمَّز الناتج بـ base64url أيضًا.

الترميز ليس تشفيرًا

يتحوّل كل جزء إلى نص بترميز base64url، وهو ترميز (encoding) يجعل البايتات آمنة داخل الروابط. والترميز ليس تشفيرًا (encryption): فكل من يحمل الرمز يستطيع فكّ الحمولة وقراءتها، دون أي مفتاح. لذا لا تضع سرًّا في JWT أبدًا.

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

جرّب: غيّر الدور (role) وانظر ماذا يقول الخادم.

جرّب

لماذا تحب الخوادم JWT، وما المشكلة؟

لأن JWT يحمل دليله معه، يستطيع الخادم التحقق منه بشيء من الحساب بدل البحث عنه في قاعدة بيانات. وكل خادم يملك المفتاح يستطيع ذلك، فيصير JWT مفيدًا حين تتقاسم خوادم كثيرة العمل.

والمشكلة هي الوجه الآخر للميزة نفسها: إن لم يبحث أحد عن الرمز، فلا أحد يستطيع إلغاءه قبل موعده. فرمز JWT المسروق يظل يعمل حتى يحين exp. لهذا تُجعل رموز الوصول قصيرة العمر، غالبًا دقائق، ويُستخدم رمز تحديث (refresh token) منفصل للحصول على رمز وصول جديد. أما رمز التحديث فيمكن إلغاؤه، لأن الخادم يبحث عنه فعلًا.

مع HS256 يصنع السرّ نفسه التوقيع ويتحقق منه، لذا فكل خادم يستطيع التحقق من الرمز يستطيع أيضًا تزويره. أما الرموز التي تنتقل بين الشركات فتستخدم RS256 أو ES256: يوقّع Google رموز الهوية بمفتاح خاص، ويستطيع أي تطبيق التحقق منها بمفتاح Google العام. وسترى حيلة زوج المفاتيح هذه مرة أخرى مع مفاتيح المرور.

اختبار سريع

مفاتيح المرور: لا شيء يُسرق

لكلمات المرور مشكلتان كبيرتان. فالخوادم تخزّن شيئًا مشتقًّا منها، يتسرّب في اختراقات البيانات. والناس يكتبونها في مواقع مزيّفة تبدو حقيقية، وهذا ما يسمى التصيّد (phishing). أما مفاتيح المرور (passkeys)، المبنية على معياري WebAuthn وFIDO2، فتستغني عن كلمة المرور كليًا.

حين تنشئ مفتاح مرور، يصنع جهازك زوج مفاتيح (key pair) جديدًا لذلك الموقع وحده. يبقى المفتاح الخاص (private key) معك: على هاتفك أو حاسوبك، أو يزامنه مدير كلمات المرور لديك مشفّرًا من طرف إلى طرف. ولا يخزّن الموقع إلا المفتاح العام (public key)، الذي يستطيع التحقق من التوقيعات لكنه لا يستطيع صنعها.

لتسجيل الدخول، يرسل الموقع تحدّيًا (challenge) عشوائيًا. فيطلب جهازك بصمة إصبعك أو وجهك أو رقمك السري (PIN)، ثم يوقّع التحدّي، ومعه عنوان الموقع الذي طلبه، بالمفتاح الخاص. ويتحقق الموقع من التوقيع بالمفتاح العام. والتحدّي جديد في كل مرة، لذا فالتوقيع الذي يسجّله أحدٌ اليوم لا ينفعه غدًا. ولا تغادر بصمتك جهازك أبدًا: فهي تفتح المفتاح فقط.

لذا لا يسرّب الاختراق إلا مفاتيح عامة لا تنفع المهاجم بشيء. وكل مفتاح مرور مربوط بنطاق الموقع الحقيقي: فعلى موقع مقلَّد مثل go0gle.com لا يملك متصفحك أي مفتاح مرور لذلك الموقع أصلًا، فلا يوجد ما يمكن خداعك لتسليمه.

كيف تجتمع معًا

الآن تستقر القطع الثلاث في مكانها. مفتاح المرور يثبت من أنت. وOAuth يقرّر ما يحق لتطبيق ما فعله نيابةً عنك. وJWT طريقة شائعة لكتابة النتائج بحيث يستطيع الخادم أن يثق بها.

مثلًا: تسجّل دخولك إلى موقع بمفتاح مرور، فيعطيك ملف تعريف ارتباط للجلسة (session cookie) أو JWT قصير العمر. أو تضغط «Sign in with Google»: فيتحقق Google منك بمفتاح مرور، ثم يستخدم OAuth وOpenID Connect ليسلّم التطبيق رمز هوية (وهو JWT) ورمز وصول.

سؤال الزعيم

اجمع كل ما تعلّمته.

اختبار سريع

انتهيت من القراءة؟

حلّ 3 اختبارات سريعة بعد لتنهي.