NAME

SignalWire::Security::WebhookValidator - Verify SignalWire webhook signatures

SYNOPSIS

use SignalWire::Security::WebhookValidator qw(
    validate_webhook_signature validate_request
);

# JSON / RELAY / SWML callbacks
if (validate_webhook_signature($signing_key, $sig_header, $url, $raw_body)) {
    # request is genuine
}

# Legacy compat-api drop-in
if (validate_request($signing_key, $sig_header, $url, \%params)) {
    # cXML / form-encoded request is genuine
}

DESCRIPTION

Implements both signature schemes from porting-sdk/webhooks.md:

Scheme A (RELAY / SWML / JSON)

lower_hex(HMAC-SHA1(key, url + raw_body))

Scheme B (Compat / cXML form)

base64(HMAC-SHA1(key, url + sorted_concat_form_params)), with URL port normalization (try both with / without :443 / :80) and an optional bodySHA256 query-param fallback for JSON-on-compat.

The combined entry point tries Scheme A first, then Scheme B in all URL / param-shape variants. All signature comparisons use a constant-time compare so the secret is not leaked across repeated requests.

ERROR MODES

Valid signature -> returns 1
Invalid signature -> returns 0
Missing $signature -> returns 0 (never throws)
Missing $signing_key -> croaks (programming error)
Reference passed as $raw_body -> croaks