July 22, 2026
2.78.0
(feat): Support webhook body-hash binding in the generated WebhooksHelper.VerifySignature
helper. When a webhook’s HMAC signature configuration declares a bodyHashBinding
(as used by providers such as Twilio for JSON bodies), verification now first
recomputes an unkeyed hash of the raw request body and compares it, in constant time,
against the hash carried in the notification URL’s query parameter, failing closed on
a missing or mismatched value before performing the existing HMAC check over the
verbatim notification URL. The body-hash algorithm and encoding are independent of the
outer HMAC’s. Output is unchanged when no bodyHashBinding is configured.
(feat): Add webhook signature verification. For APIs that configure HMAC webhook signature
verification, the C# SDK now generates a static WebhooksHelper.VerifySignature
helper (plus per-config override helpers when webhooks use distinct configs) backed
by a stdlib-only WebhookSignature core utility for HMAC computation and
constant-time comparison.
(feat): Extend the generated WebhooksHelper.VerifySignature helper to be Twilio-compatible,
mirroring the TypeScript reference. When a webhook’s HMAC configuration declares
payloadFormat.bodySort, requestBody widens to object and accepts either a raw
string or an IReadOnlyDictionary<string, ...> of POST body parameters whose values
are a string or a collection of strings; keys are sorted, per-key values are deduped
and sorted, and key + value pairs are concatenated with no separator before signing.
When a bodyHashBinding is configured, verification branches at runtime on whether the
body-hash query parameter is present on the notification URL: a JSON request recomputes
hash(rawBody), constant-time compares it, and signs the URL only, while a classic
form request signs the URL plus the sorted/deduped params with no body-hash check.
When notificationUrlNormalization is configured, the signature is verified against
several normalized forms of the notification URL (standard/absent port, and legacy
query re-encoding), succeeding on the first constant-time match via a new stdlib-only
NotificationUrlCandidates helper on the core WebhookSignature utility. The verifier
is now a pure boolean and never throws: every failure on the verification path
(null/empty inputs, a missing or malformed timestamp, an unparseable URL, a missing
body-hash parameter on the JSON path, or an unexpected request-body type) fails closed
with false. Output is unchanged for webhooks that do not configure these fields.
2.76.6
(fix): Fix a thread-safety bug in the generated OAuthTokenProvider. The token
cache is now guarded by a SemaphoreSlim with double-checked locking (the
same pattern already used by InferredAuthTokenProvider), so only one
caller refreshes the token under concurrent load and cached values are
published safely. The cache-hit path stays lock-free.