# Webhooks: Signing और Verifying — API Design और Versioning

Source: https://www.geekswithgeeks.com/hi/api-design/sec-webhooks

> बाहर जाने वाली events पर हस्ताक्षर करें और प्राप्ति पर जाँचें, replays रोकने को timestamp के साथ।

## आपके URL पर कोई भी POST कर सकता है

**Webhook** वह HTTP callback है जो घटना होने पर आपका API उपभोक्ता के URL पर करता है। चूँकि उपभोक्ता का endpoint सार्वजनिक है, उसे **भेजने वाले की पुष्टि** कर पाना ज़रूरी है। मानक तरीक़ा: साझा secret से **HMAC-SHA256** द्वारा request body पर हस्ताक्षर करें, और signature (तथा **timestamp**) header में भेजें। प्राप्तकर्ता body के **कच्चे bytes** पर HMAC दोबारा निकालता है, **constant-time** function से तुलना करता है, और **replay attacks** रोकने को कुछ मिनट से पुराने timestamps अस्वीकार करता है। Webhook भेजने वालों को विफल deliveries backoff के साथ **retry** करनी चाहिए, अनोखा **event ID** देना चाहिए ताकि प्राप्तकर्ता दोहराव हटा सकें, और उपभोक्ताओं को secrets बदलने देना चाहिए। प्राप्तकर्ताओं को जल्दी `2xx` देना और event को asynchronously प्रोसेस करना चाहिए।

## Signing और verifying, चलाकर

मैंने यह सादा-Python उदाहरण चलाया। Signature 64 अक्षरों का hex digest है। समय-सीमा के भीतर अछूती body `ok` सत्यापित होती है; एक अतिरिक्त byte वाली body ग़लत signature के रूप में अस्वीकार होती है; वही वैध संदेश 4,000 सेकंड बाद बहुत पुराना मानकर अस्वीकार होता है।

```python
import hmac, hashlib, json, time, bisect

SECRET = b"whsec_demo"
def sign(body: bytes, ts: int) -> str:
    return hmac.new(SECRET, f"{ts}.".encode() + body, hashlib.sha256).hexdigest()
def verify(body, ts, sig, now, tolerance=300):
    if abs(now - ts) > tolerance: return "rejected: too old"
    return "ok" if hmac.compare_digest(sign(body, ts), sig) else "rejected: bad signature"
body = b'{"event":"payment.succeeded","id":"pay_1"}'; ts = 1_700_000_000
sig = sign(body, ts)
print(len(sig), verify(body, ts, sig, ts + 10), verify(body + b" ", ts, sig, ts + 10), verify(body, ts, sig, ts + 4000))

```

Output:

```
64 ok rejected: bad signature rejected: too old
```

## कच्ची body जाँचें

Parse किए JSON को दोबारा serialise करने से whitespace और key क्रम बदलते हैं और signature टूटता है। मिले हुए ठीक bytes पर HMAC निकालें।

**Quiz:** हस्ताक्षरित डेटा में timestamp क्यों शामिल करें?

- [x] पुराने, दोहराए संदेश अस्वीकार करने के लिए
- [ ] Body छोटी करने के लिए
- [ ] क्योंकि HMAC को तारीख़ें चाहिए
- [ ] Delivery तेज़ करने के लिए

*Answer:* पुराने, दोहराए संदेश अस्वीकार करने के लिए. ताज़गी के बिना हमलावर पकड़ा हुआ वैध संदेश बाद में दोबारा भेज सकता है।
