الأمان وتوقيع الـ Payload
كل payload في SocialHook موقّع بـ HMAC-SHA256 باستخدام مفتاحك السري. يجب عليك التحقق من هذا التوقيع على خادمك قبل معالجة أي رسالة — هذا يحميك من الـ payloads المزيفة.
كيف يعمل التوقيع
عندما يُسلَّم SocialHook payload إلى رابط webhook الخاص بك، يحسب تجزئة HMAC-SHA256 لـ جسم الطلب الخام باستخدام مفتاحك السري. تُرسَل هذه التجزئة في رأس HTTP X-SocialHook-Signature بتنسيق sha256=<hex_digest>.
على خادمك، تحسب نفس التجزئة باستخدام نفس المفتاح السري والجسم الخام — ثم تقارن القيمتين. إذا تطابقتا، فالـ payload أصيل.
لا تتخطَّ التحقق من التوقيع أبدًا. بدونه، يمكن لأي شخص يعرف رابط webhook الخاص بك إرسال payloads مزيفة إلى خادمك.
التحقق — Node.js
Node.js / Express
const crypto = require('crypto')
function verifySocialHookSignature(req, secret) {
const header = req.headers['x-socialhook-signature']
if (!header) return false
const hash = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(req.rawBody) // must be raw Buffer
.digest('hex')
// Use timingSafeEqual to prevent timing attacks
return crypto.timingSafeEqual(
Buffer.from(hash),
Buffer.from(header)
)
}
// In your Express middleware:
app.use(express.json({
verify: (req, _, buf) => { req.rawBody = buf }
}))
app.post('/webhook', (req, res) => {
if (!verifySocialHookSignature(req, process.env.SOCIALHOOK_SECRET)) {
return res.status(401).send('Invalid signature')
}
// Safe to process
res.sendStatus(200)
})التحقق — Python
Python / Flask
import hmac
import hashlib
from flask import Flask, request, abort
import os
app = Flask(__name__)
def verify_signature(payload_body, signature_header, secret):
if not signature_header:
return False
expected = 'sha256=' + hmac.new(
secret.encode(),
payload_body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature_header)
@app.route('/webhook', methods=['POST'])
def webhook():
sig = request.headers.get('X-SocialHook-Signature')
if not verify_signature(request.data, sig, os.environ['SOCIALHOOK_SECRET']):
abort(401)
# Safe to process request.json
return '', 200التحقق — PHP
PHP
<?php
function verifySocialHookSignature($rawBody, $signatureHeader, $secret): bool {
if (empty($signatureHeader)) return false;
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);
return hash_equals($expected, $signatureHeader);
}
$rawBody = file_get_contents('php://input');
$sig = $_SERVER['HTTP_X_SOCIALHOOK_SIGNATURE'] ?? '';
if (!verifySocialHookSignature($rawBody, $sig, getenv('SOCIALHOOK_SECRET'))) {
http_response_code(401);
exit('Invalid signature');
}
$payload = json_decode($rawBody, true);
// Safe to process $payload
http_response_code(200);أفضل ممارسات الأمان
استخدم timingSafeEqual دائمًا — مقارنة السلاسل البسيطة عرضة لهجمات التوقيت. استخدم
crypto.timingSafeEqual() (Node) أو hmac.compare_digest() (Python) أو hash_equals() (PHP).وقّع الجسم الخام وليس JSON المحلل — احسب HMAC على بايتات جسم الطلب الخام قبل أي تحليل JSON. قد تنتج محللو JSON المختلفون تسلسلات بايت مختلفة.
خزّن مفتاحك السري كمتغير بيئة — لا تُضمّنه أبدًا في الكود المصدري ولا تُلزمه في مستودع.
أعد 200 قبل المعالجة — ينتظر SocialHook حتى 10 ثوانٍ للرد. أعد 200 فورًا وعالج الـ payload بشكل غير متزامن.
استخدم HTTPS فقط — لن يُسلَّم SocialHook إلا لنقاط نهاية HTTPS. نقاط HTTP العادية تُرفض عند الإعداد.
طبّق التعامل مع التكرار — في حالات نادرة قد يُسلَّم SocialHook نفس الحدث مرتين. خزّن قيم
delivery_id وتخطَّ المكررات.دوّر مفتاحك السري دوريًا — أنشئ مفتاحًا سريًا جديدًا من إعدادات لوحة التحكم وحدّث متغير البيئة على خادمك.
وجدت ثغرة أمنية؟ يرجى الإبلاغ عنها بمسؤولية إلى security@socialhook.io. لا تكشف عنها علنًا قبل أن تتاح لنا فرصة معالجتها. نرد خلال 72 ساعة.