MCPcopy
hub / github.com/openai/openai-python / verify_signature

Method verify_signature

src/openai/resources/webhooks/webhooks.py:44–115  ·  view source on GitHub ↗

Validates whether or not the webhook payload was sent by OpenAI. Args: payload: The webhook payload headers: The webhook headers secret: The webhook secret (optional, will use client secret if not provided) tolerance: Maximum age of the webhoo

(
        self,
        payload: str | bytes,
        headers: HeadersLike,
        *,
        secret: str | None = None,
        tolerance: int = 300,
    )

Source from the content-addressed store, hash-verified

42 )
43
44 def verify_signature(
45 self,
46 payload: str | bytes,
47 headers: HeadersLike,
48 *,
49 secret: str | None = None,
50 tolerance: int = 300,
51 ) -> None:
52 """Validates whether or not the webhook payload was sent by OpenAI.
53
54 Args:
55 payload: The webhook payload
56 headers: The webhook headers
57 secret: The webhook secret (optional, will use client secret if not provided)
58 tolerance: Maximum age of the webhook in seconds (default: 300 = 5 minutes)
59 """
60 if secret is None:
61 secret = self._client.webhook_secret
62
63 if secret is None:
64 raise ValueError(
65 "The webhook secret must either be set using the env var, OPENAI_WEBHOOK_SECRET, "
66 "on the client class, OpenAI(webhook_secret='123'), or passed to this function"
67 )
68
69 signature_header = get_required_header(headers, "webhook-signature")
70 timestamp = get_required_header(headers, "webhook-timestamp")
71 webhook_id = get_required_header(headers, "webhook-id")
72
73 # Validate timestamp to prevent replay attacks
74 try:
75 timestamp_seconds = int(timestamp)
76 except ValueError:
77 raise InvalidWebhookSignatureError("Invalid webhook timestamp format") from None
78
79 now = int(time.time())
80
81 if now - timestamp_seconds > tolerance:
82 raise InvalidWebhookSignatureError("Webhook timestamp is too old") from None
83
84 if timestamp_seconds > now + tolerance:
85 raise InvalidWebhookSignatureError("Webhook timestamp is too new") from None
86
87 # Extract signatures from v1,<base64> format
88 # The signature header can have multiple values, separated by spaces.
89 # Each value is in the format v1,<base64>. We should accept if any match.
90 signatures: list[str] = []
91 for part in signature_header.split():
92 if part.startswith("v1,"):
93 signatures.append(part[3:])
94 else:
95 signatures.append(part)
96
97 # Decode the secret if it starts with whsec_
98 if secret.startswith("whsec_"):
99 decoded_secret = base64.b64decode(secret[6:])
100 else:
101 decoded_secret = secret.encode()

Calls 4

get_required_headerFunction · 0.85
decodeMethod · 0.80
appendMethod · 0.45