July 22, 2026

View as Markdown

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.