सुरक्षा और HMAC साइनिंग
Savebase के भेजे हर वेबहुक अनुरोध पर HMAC-SHA256 हस्ताक्षर होता है, जिससे आप पुष्टि कर सकते हैं कि वह वास्तव में Savebase से आया है और रास्ते में बदला नहीं गया। वेबहुक इवेंट प्रोसेस करने से पहले यह हस्ताक्षर हमेशा सत्यापित करें।
हस्ताक्षर कैसे काम करता है
Savebase आपके वेबहुक के इस मान का उपयोग करके अनुरोध के मूल बॉडी पर HMAC-SHA256 चलाता है और हस्ताक्षर निकालता है: साइनिंग सीक्रेट कुंजी के रूप में। परिणाम इसमें जाता है: X-Savebase-Signature header में इस रूप में sha256=<hex-digest>.
कच्चा body इस्तेमाल करें
HMAC की गणना हमेशा इस पर करें: कच्चे अपरिवर्तित request body bytes — फिर serialise किया JSON नहीं। parse और stringify से space व key क्रम बदलकर हस्ताक्षर असफल हो सकता है।
| हेडर | मान का प्रारूप |
|---|---|
X-Savebase-Signature | sha256=abcdef0123... |
X-Savebase-Event | post.saved |
User-Agent | Savebase-Webhook/1.0 |
Node.js / Express
bash
const crypto = require('crypto');
function verifySignature(rawBody, signatureHeader, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected, 'utf8'),
Buffer.from(signatureHeader, 'utf8')
);
}
app.post(
'/savebase-webhook',
express.raw({ type: 'application/json' }),
(req, res) => {
const sig = req.headers['x-savebase-signature'];
if (!sig || !verifySignature(req.body, sig, process.env.SAVEBASE_WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body);
console.log('Event:', event.event, event.data.id);
res.sendStatus(200);
}
);Python / Flask
bash
import hmac, hashlib, os
from flask import Flask, request, abort
app = Flask(__name__)
WEBHOOK_SECRET = os.environ['SAVEBASE_WEBHOOK_SECRET']
@app.route('/savebase-webhook', methods=['POST'])
def handle_webhook():
sig_header = request.headers.get('X-Savebase-Signature', '')
raw_body = request.get_data()
expected = 'sha256=' + hmac.new(
WEBHOOK_SECRET.encode('utf-8'),
raw_body,
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, sig_header):
abort(401)
payload = request.get_json()
print('Received event:', payload['event'])
return '', 200PHP
bash
<?php
$secret = getenv('SAVEBASE_WEBHOOK_SECRET');
$rawBody = file_get_contents('php://input');
$sigHeader = $_SERVER['HTTP_X_SAVEBASE_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);
if (!hash_equals($expected, $sigHeader)) {
http_response_code(401);
exit('Invalid signature');
}
$event = json_decode($rawBody, true);
error_log('Received: ' . $event['event']);
http_response_code(200);सुरक्षा के सर्वोत्तम तरीके
- जल्दी जवाब दें। लौटाएँ:
200 OK10 सेकंड में। फिर Savebase असफल बताता है। भारी काम बैकग्राउंड में करें। - अपना हस्ताक्षर सीक्रेट कभी लॉग में न लिखें। इसे पासवर्ड जैसा मानें। इसे यहाँ बदलें:
Settings → Webhooksयदि लगे कि चोरी हुआ। - केवल HTTPS इस्तेमाल करें। Savebase साधारण HTTP एंडपॉइंट अस्वीकार करता है।
- टाइमिंग-सुरक्षित तुलना इस्तेमाल करें। हमेशा इस्तेमाल करें
crypto.timingSafeEqual(Node),hmac.compare_digest(Python), याhash_equals(PHP) — कभी भी साधारण===. - विफलताओं को खुद सँभालें। Savebase डिलीवरी का नतीजा दर्ज करता है, लेकिन मौजूदा व्यवस्था विफल अनुरोधों को अपने-आप दोबारा नहीं आज़माती और न ही रीप्ले करती है।