sdk(P1.4): inbound webhook verification helper in all three SDKs
Customers receiving Attesto webhook deliveries can now verify them with one
call, mirroring backend/app/services/webhooks/signing.py exactly: read the
X-Attesto-Timestamp / X-Attesto-Signature headers (case-insensitive), reject
when abs(now - ts) > max_skew_s (300 s default, replay protection), recompute
hex(hmac_sha256(secret, f"{timestamp}.{body}")), constant-time compare
(hmac.compare_digest / charcode-XOR fold over equal-length hex / hmac.Equal).
- Python: attesto.verify_webhook(body=, headers=, secret=, max_skew_s=, now=)
- TypeScript: verifyWebhook({ body, headers, secret, maxSkewS, now }) via
WebCrypto HMAC (edge-safe)
- Go: VerifyWebhook(body, headers, secret, maxSkewS)
New corpus golden-vectors/sdk-parity/webhook.json (valid, within-skew,
skewed-timestamp, bad-signature, tampered-body, wrong-secret,
non-numeric-timestamp) with backend-derived signatures; all three SDKs agree
on every case. READMEs gain a "Receiving Attesto webhooks" example.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
22
README.md
22
README.md
@@ -129,6 +129,28 @@ client, _ := attesto.NewClient(apiKey, attesto.WithHeadStore(attesto.NewFileHead
|
||||
client, _ = attesto.NewClient(apiKey, attesto.WithHeadStore(nil))
|
||||
```
|
||||
|
||||
## Receiving Attesto webhooks
|
||||
|
||||
```go
|
||||
func handler(w http.ResponseWriter, r *http.Request) {
|
||||
body, _ := io.ReadAll(r.Body)
|
||||
headers := map[string]string{
|
||||
"X-Attesto-Timestamp": r.Header.Get("X-Attesto-Timestamp"),
|
||||
"X-Attesto-Signature": r.Header.Get("X-Attesto-Signature"),
|
||||
}
|
||||
if !attesto.VerifyWebhook(body, headers, webhookSecret, 300) {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
process(body)
|
||||
}
|
||||
```
|
||||
|
||||
Verification recomputes `hmac_sha256(secret, "<timestamp>." + body)` from the
|
||||
`X-Attesto-Timestamp` / `X-Attesto-Signature` headers, rejects timestamps more
|
||||
than the allowed skew from now (replay protection), and compares with
|
||||
`hmac.Equal` (constant time).
|
||||
|
||||
## Operator and Admin Endpoints
|
||||
|
||||
System-key clients are created with `attesto.NewClient`. Tenant/operator
|
||||
|
||||
Reference in New Issue
Block a user