@fygaro/webhook
v1.2.0
Published
Webhook signature verification for Fygaro
Downloads
45
Readme
@fygaro/webhook
Verify Fygaro webhooks in Node / TypeScript — zero runtime deps
Works on Node ≥ 16, edge runtimes and test environments. No optional peer dependencies.
Installation
npm i @fygaro/webhookQuick start
import { FygaroWebhookValidator } from "@fygaro/webhook";
const validator = new FygaroWebhookValidator({
secrets: [
process.env.FYGARO_SECRET!, // current secret
// process.env.FYGARO_OLD_SECRET!, // add during rotation
],
// maxAge: 300, // default ⇢ 5 minutes
});
const sigHeader = req.headers["fygaro-signature"] as string;
const rawBody = req.rawBody as Buffer; // **unmodified** request body
if (!validator.verifySignature(sigHeader, rawBody)) {
res.status(400).send("Invalid signature");
return;
}
// ...process JSON, return 200...Opt-in: detailed error handling
import {
FygaroWebhookValidator,
SignatureVerificationError,
} from "@fygaro/webhook";
const validator = new FygaroWebhookValidator({
secrets: [process.env.FYGARO_SECRET!],
throwOnError: true,
});
try {
validator.verifySignature(
req.headers["fygaro-signature"] as string,
req.rawBody as Buffer,
);
} catch (err) {
if (err instanceof SignatureVerificationError) {
console.warn("Webhook rejected:", err.message);
res.status(400).send(err.message);
return;
}
}API
new FygaroWebhookValidator(options)
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| secrets | Array<string \| Uint8Array> | required | One or more active signing secrets. Provide both new and previous secrets during a rotation window. Each value may be a UTF‑8 string or a Buffer/Uint8Array. |
| maxAge | number | 300 | Acceptable clock skew (seconds) between the header timestamp and server time. Lower values reduce replay‑attack risk. |
| unsafeSkipTsValidation | boolean | false | Test‑only. When true the timestamp‑freshness check is skipped and a console warning is printed on instantiation. Never enable in production. |
| throwOnError | boolean | false | When true, failures raise subclasses of SignatureVerificationError; when false (default) the method simply returns false. |
Legacy positional constructor (deprecated)
The old positional overloads continue to work but will be removed in v2.0.0:
// v1.x (deprecated)
new FygaroWebhookValidator([secret], 300, /* skip? */ false);Creating an instance with the positional form prints a one‑time deprecation warning. Please migrate to the options object shown above.
validator.verifySignature(signatureHeader, body) → boolean
| Param | Type | Description |
|-------|------|-------------|
| signatureHeader | string | Exact value of the Fygaro‑Signature header. |
| body | Uint8Array \| Buffer \| string | Raw request body exactly as received. Do not JSON‑parse or re‑serialize. |
Returns true when:
- The HMAC matches any provided secret, and
- The header timestamp is within
maxAge(unless skipped).
Exception classes
SignatureVerificationError(base)MissingHeaderErrorTimestampInvalidErrorTimestampExpiredErrorSignatureMismatchError
Deterministic unit tests
Skip the freshness gate to keep fixtures tidy:
const validator = new FygaroWebhookValidator({
secrets: ["test-secret"],
unsafeSkipTsValidation: true,
});
expect(validator.verifySignature(header, body)).toBe(true);The first instance created with the flag prints:
[fygaro-webhook] Timestamp validation DISABLED – for test use only!Changelog
See CHANGELOG.md for full release notes.
License
MIT © Fygaro — support · [email protected]
