1010
1111# Models ---------------------------------------------------------------------
1212
13- # test
14-
1513
1614class WebhookTestPayload (BaseModel ):
1715 """Test webhook payload."""
@@ -53,20 +51,20 @@ class WebhookAgentTaskStatusUpdate(BaseModel):
5351# Methods --------------------------------------------------------------------
5452
5553
56- def create_webhook_signature (payload : Any , timestamp : str , secret : str ) -> str :
54+ def create_webhook_signature (body : Any , timestamp : str , secret : str ) -> str :
5755 """
58- Creates a webhook signature for the given payload , timestamp, and secret.
56+ Creates a webhook signature for the given body , timestamp, and secret.
5957
6058 Args:
61- payload : The webhook payload to sign
59+ body : The webhook body to sign
6260 timestamp: The timestamp string
6361 secret: The secret key for signing
6462
6563 Returns:
6664 The HMAC-SHA256 signature as a hex string
6765 """
6866
69- dump = json .dumps (payload , separators = ("," , ":" ), sort_keys = True )
67+ dump = json .dumps (body , separators = ("," , ":" ), sort_keys = True )
7068 message = f"{ timestamp } .{ dump } "
7169
7270 # Create HMAC-SHA256 signature
@@ -101,8 +99,16 @@ def verify_webhook_event_signature(
10199 else :
102100 json_data = body
103101
104- # PARSE
102+ # NOTE: Do not use the parsed json_data (model_dump()) for signature verification, use the original json_data (raw body) instead.
103+ # The signature is created from the original body, not the parsed model
104+ calculated_signature = create_webhook_signature (
105+ body = json_data , timestamp = timestamp , secret = secret
106+ )
105107
108+ if not hmac .compare_digest (expected_signature , calculated_signature ):
109+ return None
110+
111+ # PARSE
106112 webhook_event : Optional [Webhook ] = None
107113
108114 if webhook_event is None :
@@ -121,15 +127,6 @@ def verify_webhook_event_signature(
121127 if webhook_event is None :
122128 return None
123129
124- # Verify
125-
126- calculated_signature = create_webhook_signature (
127- payload = webhook_event .payload .model_dump (), timestamp = timestamp , secret = secret
128- )
129-
130- if not hmac .compare_digest (expected_signature , calculated_signature ):
131- return None
132-
133130 return webhook_event
134131
135132 except Exception :
0 commit comments