Skip to content

Commit d1dc770

Browse files
committed
Add webhook secret rotation support (WEBHOOK_SECRET_OLD)
Falls back to WEBHOOK_SECRET_OLD when primary secret fails verification, enabling zero-downtime secret rotation.
1 parent 9682c0c commit d1dc770

1 file changed

Lines changed: 13 additions & 5 deletions

File tree

app.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -376,12 +376,20 @@ async def verify_signature(request: Request, body: bytes) -> str | None:
376376
)
377377
raise HTTPException(status_code=400, detail="Missing delivery ID")
378378

379-
hash_object = hmac.new(webhook_secret.encode(), msg=body, digestmod=hashlib.sha256)
380-
expected_signature = "sha256=" + hash_object.hexdigest()
379+
def _check_secret(secret: str) -> bool:
380+
computed = hmac.new(secret.encode(), msg=body, digestmod=hashlib.sha256)
381+
return hmac.compare_digest("sha256=" + computed.hexdigest(), signature)
381382

382-
if not hmac.compare_digest(expected_signature, signature):
383-
logger.error("Invalid signature", extra={"error_code": "invalid_signature"})
384-
raise HTTPException(status_code=403, detail="Invalid signature")
383+
if not _check_secret(webhook_secret):
384+
old_secret = os.environ.get("WEBHOOK_SECRET_OLD")
385+
if old_secret and _check_secret(old_secret):
386+
logger.info(
387+
"Signature verified with old webhook secret (rotation in progress)",
388+
extra={"delivery_id": delivery_id},
389+
)
390+
else:
391+
logger.error("Invalid signature", extra={"error_code": "invalid_signature"})
392+
raise HTTPException(status_code=403, detail="Invalid signature")
385393

386394
return delivery_id
387395

0 commit comments

Comments
 (0)