← رجوع

كيف تحمي Webhooks و API Keys في Laravel

R

UNIXMAN

Apr 01, 2026

Article Image

في أحد المشاريع، كنت أتعامل مع Webhook بسيط يستقبل بيانات من خدمة خارجية… كل شيء كان يعمل بشكل ممتاز.

لكن المشكلة ظهرت لاحقًا: بدأ يصلني traffic غريب… requests بنفس شكل الـ webhook لكن من مصادر مجهولة.

وقتها اكتشفت أن المشكلة ليست في الكود… بل في الحماية.

الـ Webhooks و API Keys إذا لم يتم تصميمها بشكل صحيح، تصبح نقطة دخول سهلة لأي شخص.


1. الاعتماد على API Key فقط

في البداية كنت أستخدم شيء بسيط:


if ($request->header('X-API-KEY') !== env('API_KEY')) {
    abort(403);
}

وكان يبدو كافي… لكنه ليس كذلك.

المشكلة:

  • يمكن تسريب الـ API Key بسهولة
  • لا يوجد تحقق من مصدر الطلب
  • لا يوجد حماية من replay attacks

الـ API Key وحده لا يكفي.


2. عدم التحقق من توقيع الطلب (Signature)

أحد أهم الأخطاء هو عدم التحقق من أن الطلب فعلاً صادر من المصدر الصحيح.

الحل هو استخدام HMAC signature.


$signature = $request->header('X-Signature');

$computed = hash_hmac(
    'sha256',
    $request->getContent(),
    config('services.webhook.secret')
);

if (!hash_equals($signature, $computed)) {
    abort(403);
}

بهذا الشكل، حتى لو تم تسريب الـ endpoint، لا يمكن تقليد الطلب بدون الـ secret.


3. عدم استخدام Timestamp (هجوم Replay)

حتى مع وجود signature… يمكن إعادة إرسال نفس الطلب.

الحل:


$timestamp = $request->header('X-Timestamp');

if (abs(time() - $timestamp) > 300) {
    abort(403);
}

هنا نسمح فقط بطلبات خلال 5 دقائق.

بهذا تمنع إعادة استخدام نفس الطلب لاحقًا.


4. تخزين API Keys بشكل غير آمن

رأيت مشاريع تخزن API Keys بشكل plain text في قاعدة البيانات.

هذا خطر كبير.

الحل:


$key = Str::random(40);

$hashed = hash('sha256', $key);

ApiKey::create([
    'key' => $hashed,
]);

وعند التحقق:


$incoming = hash('sha256', $request->header('X-API-KEY'));

ApiKey::where('key', $incoming)->exists();

بهذا الشكل لا يمكن استرجاع المفتاح حتى لو تم اختراق قاعدة البيانات.


5. عدم تقييد الصلاحيات (Scopes)

كل API Key يجب أن يكون له صلاحيات محددة.

مثال:

  • قراءة فقط
  • إرسال بيانات
  • الوصول إلى webhook معين

بدلاً من مفتاح واحد لكل شيء.

في Laravel:


if (!$apiKey->can('create_orders')) {
    abort(403);
}

6. عدم تحديد مصدر الطلب (IP Whitelisting)

إذا كنت تعرف مصدر الـ webhook، قم بتقييده:


$allowed = ['1.2.3.4', '5.6.7.8'];

if (!in_array($request->ip(), $allowed)) {
    abort(403);
}

هذا يقلل الهجمات بشكل كبير.


7. عدم تسجيل ومحاولة تتبع الهجمات

إذا لم تقم بتسجيل الطلبات، لن تعرف أن هناك مشكلة.


Log::warning('Invalid webhook attempt', [
    'ip' => $request->ip(),
    'payload' => $request->all(),
]);

التسجيل مهم لفهم ما يحدث.


8. عدم وجود Rate Limiting

أي endpoint بدون limit هو هدف سهل.

في Laravel:


Route::post('/webhook', Controller::class)
    ->middleware('throttle:60,1');

هذا يمنع abuse بسهولة.


9. استخدام نفس المفتاح لكل العملاء

هذا من أخطر الأخطاء.

يجب أن يكون لكل عميل API Key خاص به.

حتى تستطيع:

  • تعطيل عميل معين
  • تتبع الاستخدام
  • تحديد الصلاحيات