مصادقة واجهات API

مصادقة واجهات API (API Authentication) هي الطريقة التي تعرف بها الواجهة من أرسل الطلب. فلا توجد شاشة تسجيل دخول بين العميل والواجهة، لذلك يُرفق العميل بكل طلب بيانات اعتماد (Credentials): مفتاح API، أو معرّف مستخدم وكلمة مرور (Basic)، أو رمزاً (Bearer)، ويفحصها الخادم أولاً. فتطبيق الجوال الذي يستدعي GET /v1/orders/9021 يرسل Authorization: Bearer mF_9.B5f-4.1JqM، وتجيب الواجهة بـ 200 إن كان الرمز صالحاً، وبـ 401 إن كان مفقوداً أو غير صالح.

يشرح هذا الدرس ما ترسله المخططات الثلاثة الشائعة، وأين يجوز أن تنتقل بيانات الاعتماد، وكيف تختبر أن الواجهة ترفض كل ما عدا ذلك. أما ما يُسمح للمستدعي المعروف بفعله، أي التفويض (Authorization)، فيأتي لاحقاً في هذه الوحدة التعليمية.

لماذا يهم

نقطة النهاية التي تتخطى فحص بيانات الاعتماد تسلّم بياناتها أو عملياتها لكل من يصل إليها. ولا يكشف الاستخدام العادي هذه الثغرة، لأن العملاء الحقيقيين يرسلون دائماً رمزاً صالحاً؛ ولا يجدها إلا اختبار يرسل عمداً بيانات اعتماد مفقودة أو خاطئة أو منتهية الصلاحية. وتدرج قائمة ⁦OWASP API Security Top 10 (2023)⁩ المصادقة المعطّلة (Broken Authentication) في البند ⁦API2⁩.

وتتسرّب بيانات الاعتماد أيضاً دون أن ينتبه أحد: مفتاح في رابط URL ينتهي في سجلات الوصول، وترويسة Basic في لقطة شاشة هي كلمة مرور مقروءة، ورمز يظل صالحاً بعد تسجيل الخروج يبقى في يد من نسخه. وفهم كل مخطط يمنع فريق الاختبار من أن يكون هو مصدر التسرّب.

مفاتيح API وBasic وBearer: ماذا يرسل كل منها

تستخدم معظم الواجهات واحداً من ثلاثة مخططات مصادقة (Authentication Schemes)، والعقد يحدد أيّها. ففي مستند OpenAPI يُظهر securitySchemes إما type: apiKey مع الترويسة (أو معامل الاستعلام) التي تحمل المفتاح، وإما type: http مع scheme: basic أو scheme: bearer، وهما يستخدمان ترويسة Authorization القياسية.

وتنتقل الثلاثة كلها في ترويسة الطلب (Request Header) ولا يحمي أيٌّ منها نفسه: فمن ينسخ الترويسة يستطيع إعادة إرسال الطلب، ولذلك يعتمد كل مخطط على HTTPS.

  • مفتاح API: سلسلة عشوائية طويلة تُصدر لتطبيق عميل وتُرسل في ترويسة تختارها الواجهة، مثل X-API-Key. ولا يعرّفه معيار واحد. ويعرّف المفتاح التطبيقَ المستدعي لا شخصاً بعينه، إذ تنص OWASP على أن مفاتيح API لمصادقة عملاء الواجهة لا المستخدمين. ويبقى المفتاح عادةً صالحاً حتى يُدوَّر (أي يُستبدل بمفتاح جديد) أو يُلغى.
  • مصادقة Basic (RFC 7617): يصل العميل معرّف المستخدم بكلمة المرور بعلامة النقطتين (:)، ثم يرمّز الناتج بـ Base64 ويرسله بعد كلمة Basic. وBase64 ترميز (Encoding) لا تشفير (Encryption): فالقيمة أدناه يُفكّ ترميزها إلى qa.tester:S4mple-pass. وتُرسل كلمة المرور مع كل طلب وتظل تعمل حتى تُغيَّر، والمواصفة لا تعدّ هذا المخطط آمناً من دون TLS.
  • رمز Bearer (RFC 6750): يحصل العميل أولاً على رمز، من نقطة نهاية لتسجيل الدخول مثلاً أو من خادم تفويض OAuth 2.0، ثم يرسله بعد كلمة Bearer. وأي طرف يملك رمز الحامل (Bearer Token) يستطيع استخدامه، لذا توصي المواصفة برموز قصيرة العمر (ساعة واحدة أو أقل) مقيّدة بالواجهة المقصودة بها. وكثير من رموز Bearer هي رموز JWT، وسيأتي شرحها لاحقاً في هذه الوحدة التعليمية.
تنتقل مفاتيح API وBasic وBearer كلها في ترويسة الطلب، لكن المفتاح المنسوخ يعمل حتى يُلغى، وقيمة Basic تُفك إلى كلمة المرور، ورمز Bearer يعمل حتى تنتهي صلاحيته.

مفتاح APIبلا معيار واحد

سلسلة عشوائية طويلة تُصدر لتطبيق عميل، في ترويسة تسمّيها الواجهة

X-API-Key: demo_7Hq2LmZ9pR4tKx

ما يعرّفه:
التطبيق المستدعي لا شخصاً بعينه
إذا نسخه أحدهم:
يعمل لديه حتى يُدوَّر المفتاح أو يُلغى
التحدي مع 401:
لا تحدٍّ قياسي: العقد هو الذي يحدده
أول الاختبارات السلبية:
مفقود، ملغى، مرسل في سلسلة الاستعلام

مصادقة BasicRFC 7617

user-id:password مرمَّزة بـ Base64 وتُرسل بعد كلمة Basic

Authorization: Basic cWEudGVzdGVyOlM0bXBsZS1wYXNz

ما يعرّفه:
المستخدم الذي يحمل معرّفه وكلمة مروره
إذا نسخه أحدهم:
فك الترميز يكشف كلمة المرور، وتبقى صالحة حتى تُغيَّر
التحدي مع 401:
WWW-Authenticate: Basic realm="api"
أول الاختبارات السلبية:
كلمة مرور خاطئة، مستخدم غير معروف، ورسالة خطأ واحدة للحالتين

رمز BearerRFC 6750

رمز يُحصل عليه أولاً ويُرسل بعد كلمة Bearer، ومن يحمله يستطيع استخدامه

Authorization: Bearer mF_9.B5f-4.1JqM

ما يعرّفه:
المستخدم أو العميل الذي أُصدر له
إذا نسخه أحدهم:
يعمل لديه حتى تنتهي صلاحيته أو يُلغى
التحدي مع 401:
WWW-Authenticate: Bearer realm="orders"
أول الاختبارات السلبية:
مفقود، حرف واحد مغيَّر، منتهي الصلاحية، مستخدم بعد تسجيل الخروج

القيم في الأمثلة مختلَقة لهذا الدرس. ويستطيع كل من يرى الطلب إعادة إرسال أيٍّ من الثلاثة، لذا يحتاج كل منها إلى HTTPS.

النسخة النصية
API key:  X-API-Key: demo_7Hq2LmZ9pR4tKx
Basic:    Authorization: Basic cWEudGVzdGVyOlM0bXBsZS1wYXNz
Bearer:   Authorization: Bearer mF_9.B5f-4.1JqM

جرّبها: مفكّك ترميز Base64 جرّبها: مرمّز Base64

أين تنتقل بيانات الاعتماد: في الترويسات لا في الروابط

بيانات الاعتماد الموضوعة في رابط URL تُنسخ إلى أماكن لا يحميها أحد: سجلات الوصول في الخوادم والوكلاء (Proxies)، وأدوات المراقبة، وسجل المتصفح، وكل تذكرة يلصق فيها أحدهم الرابط. وتنبّه RFC 9110 إلى أن كثيراً من الخوادم والوكلاء والمتصفحات تسجّل الرابط المطلوب أو تعرضه، فلا مكان فيه لمعلومات حساسة، وتمنع المرسل من وضع user:password@ في روابط http وhttps؛ وتنص RFC 6750 على ألا يُرسل رمز Bearer في معامل استعلام (SHOULD NOT) إلا إذا لم تكن هناك طريقة أخرى؛ وتعدّ OWASP الرموز وكلمات المرور في الرابط مصادقةً معطّلة.

والقاعدة عند المختبِر: تنتقل بيانات الاعتماد في ترويسة، عبر HTTPS، ولا تُعاد في رسالة خطأ ولا تُكتب في سجل. وإذا قبلتها الواجهة في سلسلة الاستعلام أيضاً، فأبلغ عن ذلك بوصفه خطراً حتى لو «نجح» الطلب.

# Leaks: the key is part of the URL and is written to access logs
GET /v1/products?api_key=demo_7Hq2LmZ9pR4tKx HTTP/1.1
Host: api.shop.test

# Expected: the key travels in a header, over HTTPS
GET /v1/products HTTP/1.1
Host: api.shop.test
X-API-Key: demo_7Hq2LmZ9pR4tKx

جرّبها: منشئ ترويسات API جرّبها: مولّد أوامر cURL

ماذا تختبر في كل نقطة نهاية محمية

كما بيّن درس «المصادقة والتفويض»، تخصص RFC 9110 الحالة 401 للطلب الذي يفتقر إلى بيانات اعتماد صالحة، مع تحدٍّ (Challenge) في ترويسة WWW-Authenticate، والحالة 403 للطلب الذي فهمه الخادم ويرفض تنفيذه. وفي واجهة API يسمّي هذا التحدي المخطط المطلوب، مثل WWW-Authenticate: Basic realm="api" أو WWW-Authenticate: Bearer realm="orders"، حيث يسمّي realm المنطقة المحمية. وليس لمفاتيح API تحدٍّ قياسي، فالعقد هو الذي يحدده. وحين يكون المستدعي معروفاً فالحالة 403 قرار تفويض، وله درسه الخاص؛ أما الحالات أدناه فتختبر المصادقة وحدها.

  • الغياب: لا بيانات اعتماد ← 401 مع تحدٍّ.
  • قيمة مشوّهة أو مخطط خاطئ: قيمة فارغة، أو Bearer بلا رمز، أو Basic مرسلة إلى واجهة لا تقبل إلا Bearer ← 401، وليس 500 أبداً. وقد يردّ العقد الذي يتّبع RFC 6750 على ترويسة Bearer المشوّهة بـ 400 مع error="invalid_request" بدلاً من ذلك.
  • بيانات غير صالحة: كلمة مرور خاطئة، أو مستخدم غير معروف، أو مفتاح أو رمز غُيّر فيه حرف واحد ← 401.
  • انتهاء الصلاحية أو الإلغاء: رمز تجاوز وقت انتهائه، أو مفتاح أُلغي، أو رمز استُخدم بعد تسجيل الخروج إذا نص العقد على أن الخروج يلغيه ← 401.
  • الموضع الخاطئ: بيانات الاعتماد في سلسلة الاستعلام أو تحت اسم ترويسة آخر ← رفض.
  • كل نقطة نهاية وكل طريقة: حماية GET لا تثبت شيئاً عن DELETE على المسار نفسه، ولا عن الإصدارات الأقدم من الواجهة التي ما زالت منشورة.
  • أخطاء آمنة: رسالة واحدة للمستخدم غير المعروف ولكلمة المرور الخاطئة، ولا تتبّع للمكدس (Stack Trace)، ولا تُعاد بيانات الاعتماد في الاستجابة أبداً.

جرّبها: مختبِر مصادقة API

مثال تطبيقي: نقطة نهاية للطلبيات محمية برموز Bearer

ينص العقد على: «يتطلب GET وDELETE /v1/orders/{id} الترويسة Authorization: Bearer <token>. وتنتهي صلاحية الرمز بعد 30 دقيقة من إصداره ويُلغى عند تسجيل الخروج. والرمز المفقود أو غير الصالح يعيد 401». ومع مستخدم الاختبار A، اكتب كل حالة وإجابتها المتوقعة قبل أن ترسل أي طلب:

يحتاج الصفان 5 و6 إلى توقيت وإلى تسجيل خروج. ويطبّق الصف 5 تحليل القيم الحدّية بصيغته الثنائية (2-value BVA) على عمر الرمز البالغ 30 دقيقة: فالدقيقة 30 هي أول قيمة منتهية الصلاحية، أما الرمز الذي عمره 29 دقيقة، وهو آخر قيمة صالحة، فيجب أن يظل يعيد 200. وإذا منح الخادم مهلة إضافية لفروق التوقيت بين الساعات، فيجب أن ينص العقد عليها. ويفحص الصف 9 الحالة أيضاً: فإذا أعادت الواجهة 401 وحذفت الطلبية رغم ذلك فهذا عيب (Defect). أما رمز المستخدم B على طلبية تخص A فاختبار تفويض لدرس لاحق. ويذكر تقرير الخطأ (Bug Report) لصفٍّ فاشل الطلب بالضبط، والحالة والترويسات المستلمة، والإجابة المتوقعة، مع إخفاء بيانات الاعتماد.

#  Request to /v1/orders/9021 (A's order)    Expected
1  GET, valid token of user A                200, order JSON
2  GET, no Authorization header              401, WWW-Authenticate: Bearer realm="orders"
3  GET, Authorization: Bearer (empty value)  401
4  GET, token with last character changed    401, error="invalid_token" in the challenge
5  GET, token issued 30 minutes ago          401, error="invalid_token" in the challenge
6  GET, token of A after A logged out        401
7  GET, Authorization: Basic (A's password)  401, challenge names Bearer
8  GET, valid token in ?access_token=        401; if accepted, report it as a risk
9  DELETE, no Authorization header           401, and order 9021 still exists

جرّبها: مختبِر مصادقة API جرّبها: مولّد أوامر cURL

أخطاء شائعة

  • اختبار المسار السعيد وحده برمز صالح، وافتراض أن نقطة النهاية محمية.
  • معاملة Base64 كأنها حماية: ترويسة Basic في سجل أو في لقطة شاشة هي كلمة مرور مقروءة.
  • قبول أي استجابة 4xx: فلـ 401 و403 معنيان مختلفان، واستجابة 401 يجب أن تحمل WWW-Authenticate.
  • فحص GET وحدها، ونسيان طرق الكتابة والإصدارات الأقدم من الواجهة.
  • لصق رموز أو مفاتيح أو كلمات مرور حقيقية في تقارير الأخطاء أو المحادثات أو المجموعات المشتركة بدلاً من إخفائها.
  • عدم اختبار انتهاء الصلاحية والإلغاء أبداً، فيمرّ دون ملاحظة رمزٌ يظل يعمل بعد تسجيل الخروج.

من منظور ضمان الجودة

مكان أسئلة المصادقة هو مراجعة العقد: أي مخطط، وأي ترويسة، وكم يعيش الرمز، وماذا يفعل تسجيل الخروج، وكيف تبدو استجابة 401. اسأل المطور حين يترك مستند OpenAPI أياً من ذلك مفتوحاً، واتفقوا على حسابات الاختبار والمفاتيح التي يملكها فريق الاختبار في كل بيئة.

سجّل في كل اختبار نوع بيانات الاعتماد والحساب المستخدم، لا السرّ نفسه، واحفظ مفاتيح الاختبار في مخزن الأسرار لدى الفريق أو في متغيرات البيئة. وأبلغ عن نقطة النهاية التي تقبل طلباً بلا بيانات اعتماد صالحة بوصفها عيباً أمنياً، وخطورته عادةً حرج (Critical) أو حاجب (Blocker). ولا تُجرِ اختبارات المصادقة إلا على أنظمة تملكها أو لديك إذن مكتوب باختبارها.

تمرين عملي

راجع سجل اختبار مصادقة

المطلوب

أجرى زميل لك اختبارات مصادقة على واجهة الطلبيات من المثال التطبيقي، بالعقد نفسه، وحفظ السجل أدناه.

قرّر لكل صف هل تصرّفت الواجهة تصرفاً صحيحاً، ولكل عيب اذكر ما كان متوقعاً ومدى خطورته.

المادة
Orders API, test environment, endpoint /v1/orders/9021
#  Method and credential                   Status  Observed
1  GET, valid token of user A              200     order JSON
2  GET, no Authorization header            401     WWW-Authenticate: Bearer realm="orders"
3  GET, token with last character changed  200     order JSON
4  GET, token of A after A logged out      200     order JSON
5  GET, Authorization: Basic               500     stack trace in the body
      cWEubGVhZDpXaW50ZXItVGVhLTQy
6  GET, ?access_token=<valid token of A>   200     order JSON
7  DELETE, no Authorization header         204     empty body
8  GET, token issued 35 minutes ago        401     no WWW-Authenticate header
الخطوات
  1. اكتب النتيجة المتوقعة لكل صف من العقد ومن RFC 9110.
  2. صنّف كل صف: صحيح أم عيب.
  3. فكّ ترميز القيمة في الصف 5 بأداة لفك ترميز Base64، ودوّن ما يعنيه ذلك بالنسبة إلى السجل نفسه.
  4. رتّب العيوب حسب الخطورة، واكتب عنوان تقرير خطأ لأخطرها.
إظهار الإجابة النموذجية
الإجابة النموذجية

الصفان 1 و2 صحيحان.

الصف 3 حرج (Critical): المتوقع 401 مع error="invalid_token"، لكن قُبل رمز معدَّل، فالرموز لا يُتحقق منها وقد يعمل أي رمز مختلَق. والصف 4 رئيسي (Major): المتوقع 401، لكن تسجيل الخروج لا يلغي الرمز، خلافاً للعقد.

الصف 5 رئيسي: المتوقع 401 مع WWW-Authenticate: Bearer، لا استجابة 500 تسرّب تتبّع المكدس. والقيمة تُفك إلى qa.lead:Winter-Tea-42، أي أن السجل نفسه يكشف كلمة مرور اختبار: أخفِ بيانات الاعتماد في السجلات والتقارير، واطلب تغيير كلمة المرور هذه.

الصف 6 رئيسي: المتوقع 401، لكن قُبل الرمز في الرابط، حيث تحتفظ به سجلات الوصول. والعقد لا يذكر إلا الترويسة، وRFC 6750 تقول SHOULD NOT، فأبلغ عنه عيباً أمنياً أو خطراً يقرر فيه الفريق.

الصف 7 هو الأخطر، حاجب (Blocker) أو حرج: نجح طلب DELETE مجهول الهوية. تأكد أن الطلبية 9021 حُذفت، ثم أبلغ بالعنوان: «DELETE /v1/orders/{id} يحذف الطلبية دون ترويسة Authorization ويعيد 204 بدلاً من 401».

الصف 8: الرفض صحيح، لكن RFC 9110 تشترط WWW-Authenticate مع كل استجابة 401، فهذا عيب ثانوي (Minor). الترتيب المقترح: 7، 3، 4، 6، 5، 8.

أسئلة شائعة

هل ما زالت مصادقة Basic مقبولة في واجهات API؟

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

هل يعيد غياب بيانات الاعتماد 401 أم 403؟

401، كما يشرح درس «المصادقة والتفويض». وفي واجهة تستخدم Bearer تميّز RFC 6750 أيضاً بين نوعَي الاستجابة 401: فالطلب الذي لم يرسل بيانات اعتماد ينبغي أن يتلقى تحدياً بلا السمة error، أما الطلب الذي يحمل رمزاً منتهي الصلاحية أو ملغى أو غير صالح فينبغي أن يتلقى error="invalid_token" في التحدي. لذلك يفحص اختبار الرمز المنتهي التحدي نفسه، لا الحالة 401 وحدها.

هل يكفي مفتاح API لحماية بيانات المستخدمين؟

عادةً لا يكفي وحده. فالمفتاح يعرّف التطبيق المستدعي لا الشخص الذي يستخدمه، ويعيش مدة طويلة. وتنص ⁦OWASP API Security Top 10 (2023)⁩ على أن مفاتيح API لمصادقة عملاء الواجهة لا المستخدمين؛ أما بيانات المستخدمين فتحتاج إلى مصادقة المستخدم، وتكون عادةً برمز.

ما الفرق بين رمز Bearer وJWT؟

كلمة Bearer تصف طريقة استخدام الرمز: من يحمله يستطيع تقديمه. أما JWT فصيغة لمحتوى الرمز. وقد يكون رمز Bearer بصيغة JWT، أو سلسلة عشوائية لا يعرف معناها إلا الخادم الذي يبحث عنها في سجلاته. ويشرح دليل JWT هذه الصيغة.

المراجع

  • RFC 6750: The OAuth 2.0 Authorization Framework: Bearer Token UsageIETF · 2012كيف يُرسَل رمز bearer (Authorization: Bearer …) واستجابات الخطأ التي يعيدها خادم الموارد.
  • RFC 7617: The 'Basic' HTTP Authentication SchemeIETF · 2015كيف يرمّز التوثيق Basic الزوج user-id:password في ترويسة Authorization، ولماذا يحتاج إلى TLS.
  • RFC 9110: HTTP SemanticsIETF · 2022معاني أساليب HTTP وحقول الترويسات ورموز الحالة والتفاوض على المحتوى، بغضّ النظر عن إصدار البروتوكول.
  • OWASP API Security Top 10 (2023)OWASP Foundation · 2023أكثر عشر نقاط ضعف شيوعاً في واجهات API: خلل التفويض على مستوى الكائن، وخلل التوثيق، والاستهلاك غير المقيد للموارد، وغيرها.

تدرّب بأدوات متقن

اختبر مصادقة Bearer وBasic ومفتاح API والترويسات المخصّصة على نقطة نهاية وقارن الاستجابات المصرّح بها بغير المصرّح بها.

اختبار واجهات API

فكّ ترميز سلاسل Base64 أو Base64url إلى نص، مع إصلاح الحشو تلقائياً.

الترميز

ترميز النصوص أو الملفات إلى Base64 (القياسي أو الآمن لعناوين URL) داخل متصفحك.

الترميز

إنشاء ترويسات الطلبات لواجهات REST API (المصادقة والتفاوض على المحتوى والتتبّع) وتصديرها إلى cURL أو fetch أو axios أو HTTP.

الويب

إنشاء أوامر cURL من الطريقة وعنوان URL والترويسات والمتن وخيارات المصادقة.

الويب

للتعمّق أكثر

تقدّمك في هذا الموضوع

جزء من مسار تعلم ضمان الجودة