@earendil-works/mailhook 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,24 +5,55 @@ import { WebhookEvent } from "./_internals/types.ts";
5
5
  /**
6
6
  * Parse a webhook event payload into a WebhookEvent object.
7
7
  *
8
+ * This does not verify the signature; use `verifyAndParseWebhook` for
9
+ * untrusted input.
10
+ *
8
11
  * @param payload - The webhook payload as a string, Buffer, or object
9
12
  * @returns The parsed webhook event
10
13
  * @throws Error if the payload is invalid or cannot be parsed
11
14
  */
12
15
  export declare function parseWebhookEvent(payload: string | Buffer | Record<string, unknown>): WebhookEvent;
16
+ /** Default tolerance in seconds for the webhook-timestamp header (replay protection). */
17
+ export declare const DEFAULT_TOLERANCE_SECONDS = 300;
18
+ /**
19
+ * Options for webhook verification.
20
+ */
21
+ export interface WebhookVerifyOptions {
22
+ /**
23
+ * Maximum allowed difference in seconds between the `webhook-timestamp`
24
+ * header and the current time (default 300). Older or future deliveries are
25
+ * rejected to prevent replay attacks. `null` disables the check, which is
26
+ * not recommended.
27
+ */
28
+ toleranceSeconds?: number | null;
29
+ /** The current time, for testing. Defaults to `Date.now()`. */
30
+ now?: Date | number;
31
+ }
32
+ /**
33
+ * Error thrown when a webhook delivery cannot be verified.
34
+ */
35
+ export declare class WebhookVerificationError extends Error {
36
+ constructor(message: string);
37
+ }
13
38
  /**
14
- * Validate a webhook signature.
39
+ * Validate a Standard Webhooks signature.
15
40
  *
16
- * Supports both Standard Webhooks format (v1,base64_signature) and legacy format (hex).
41
+ * Mailhook signs `${webhookId}.${timestamp}.${payload}` with HMAC-SHA256
42
+ * keyed with the base64-decoded webhook secret and sends it as
43
+ * `v1,<base64 signature>` in the `webhook-signature` header.
17
44
  *
18
- * @param payload - The raw webhook payload
19
- * @param signature - The signature from the webhook headers (Webhook-Signature or X-Webhook-Signature)
20
- * @param secret - The webhook secret (may be base64 encoded for Standard Webhooks)
21
- * @param timestamp - The timestamp from Webhook-Timestamp header (for Standard Webhooks)
22
- * @param webhookId - The webhook ID from Webhook-Id header (for Standard Webhooks)
23
- * @returns True if the signature is valid, false otherwise
45
+ * @param payload - The raw webhook request body, exactly as received
46
+ * @param signature - The `webhook-signature` header. It may contain several
47
+ * space separated `v1,<base64>` signatures; any valid one is accepted.
48
+ * @param secret - The webhook secret, `whsec_<base64>` or bare base64
49
+ * @param timestamp - The `webhook-timestamp` header (Unix seconds)
50
+ * @param webhookId - The `webhook-id` header
51
+ * @param options - Timestamp tolerance (default 300 seconds) and clock override
52
+ * @returns True if the signature is valid and the timestamp is within the
53
+ * tolerance, false otherwise
54
+ * @throws Error if the secret is not valid base64
24
55
  */
25
- export declare function validateWebhookSignature(payload: Buffer | string, signature: string, secret: string, timestamp: string, webhookId: string): boolean;
56
+ export declare function validateWebhookSignature(payload: Buffer | string, signature: string, secret: string, timestamp: string, webhookId: string, options?: WebhookVerifyOptions): boolean;
26
57
  /**
27
58
  * Headers interface for webhook verification
28
59
  */
@@ -33,19 +64,22 @@ export interface WebhookHeaders {
33
64
  [key: string]: string | undefined;
34
65
  }
35
66
  /**
36
- * Verify webhook signature and parse the event.
67
+ * Verify a webhook delivery and parse the event.
37
68
  *
38
- * This is a convenience function that combines signature validation
39
- * and event parsing.
69
+ * The signature, timestamp and webhook id are taken from the explicit
70
+ * arguments or, if not given, from `headers` (looked up case-insensitively).
40
71
  *
41
- * @param payload - The raw webhook payload
42
- * @param secret - The webhook secret
43
- * @param signature - The signature from the webhook headers
44
- * @param timestamp - The timestamp from webhook-timestamp header
45
- * @param webhookId - The webhook id from webhook-id header
46
- * @param headers - A mapping of http headers (case insensitive) as alternative to signature, timestamp and webhookId
72
+ * @param payload - The raw webhook request body, exactly as received
73
+ * @param secret - The webhook secret, `whsec_<base64>` or bare base64
74
+ * @param signature - The `webhook-signature` header
75
+ * @param timestamp - The `webhook-timestamp` header
76
+ * @param webhookId - The `webhook-id` header
77
+ * @param headers - The request headers, as an alternative to signature, timestamp and webhookId
78
+ * @param options - Timestamp tolerance (default 300 seconds) and clock override
47
79
  * @returns The parsed webhook event
48
- * @throws Error if the signature is invalid or payload cannot be parsed
80
+ * @throws WebhookVerificationError if a header is missing, the timestamp is
81
+ * outside the tolerance or the signature is invalid
82
+ * @throws Error if the secret is not valid base64 or the payload cannot be parsed
49
83
  */
50
- export declare function verifyAndParseWebhook(payload: Buffer | string, secret: string, signature?: string, timestamp?: string, webhookId?: string, headers?: WebhookHeaders): WebhookEvent;
84
+ export declare function verifyAndParseWebhook(payload: Buffer | string, secret: string, signature?: string, timestamp?: string, webhookId?: string, headers?: WebhookHeaders, options?: WebhookVerifyOptions): WebhookEvent;
51
85
  //# sourceMappingURL=webhook.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/mailhook/webhook.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjD,YAAY,CAgBd;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAmDT;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,cAAc,GACvB,YAAY,CA+Bd"}
1
+ {"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/mailhook/webhook.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjD,YAAY,CAgBd;AAED,yFAAyF;AACzF,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,+DAA+D;IAC/D,GAAG,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,OAAO,EAAE,MAAM;CAI5B;AA4DD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CA+CT;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,cAAc,EACxB,OAAO,GAAE,oBAAyB,GACjC,YAAY,CA0Cd"}
@@ -6,6 +6,9 @@ import { WebhookEvent } from "./_internals/types.js";
6
6
  /**
7
7
  * Parse a webhook event payload into a WebhookEvent object.
8
8
  *
9
+ * This does not verify the signature; use `verifyAndParseWebhook` for
10
+ * untrusted input.
11
+ *
9
12
  * @param payload - The webhook payload as a string, Buffer, or object
10
13
  * @returns The parsed webhook event
11
14
  * @throws Error if the payload is invalid or cannot be parsed
@@ -28,80 +31,137 @@ export function parseWebhookEvent(payload) {
28
31
  }
29
32
  return WebhookEvent.fromApiDict(data);
30
33
  }
34
+ /** Default tolerance in seconds for the webhook-timestamp header (replay protection). */
35
+ export const DEFAULT_TOLERANCE_SECONDS = 300;
36
+ /**
37
+ * Error thrown when a webhook delivery cannot be verified.
38
+ */
39
+ export class WebhookVerificationError extends Error {
40
+ constructor(message) {
41
+ super(message);
42
+ this.name = "WebhookVerificationError";
43
+ }
44
+ }
45
+ const BASE64_RE = /^[A-Za-z0-9+/]*={0,2}$/;
46
+ // Strictly decode standard base64; returns null for anything else.
47
+ // Buffer.from(..., "base64") never throws and silently skips invalid input.
48
+ function decodeBase64Strict(value) {
49
+ if (value.length % 4 !== 0 || !BASE64_RE.test(value)) {
50
+ return null;
51
+ }
52
+ const decoded = Buffer.from(value, "base64");
53
+ if (decoded.toString("base64") !== value) {
54
+ return null;
55
+ }
56
+ return decoded;
57
+ }
58
+ function decodeSecret(secret) {
59
+ const raw = secret.startsWith("whsec_") ? secret.slice(6) : secret;
60
+ const decoded = decodeBase64Strict(raw);
61
+ if (!decoded) {
62
+ throw new Error("Invalid webhook secret: expected base64, optionally prefixed with 'whsec_'");
63
+ }
64
+ return decoded;
65
+ }
66
+ function checkTimestamp(timestamp, options = {}) {
67
+ if (!/^\d+$/.test(timestamp)) {
68
+ throw new WebhookVerificationError("Invalid webhook timestamp");
69
+ }
70
+ const tolerance = options.toleranceSeconds === undefined
71
+ ? DEFAULT_TOLERANCE_SECONDS
72
+ : options.toleranceSeconds;
73
+ if (tolerance === null) {
74
+ return;
75
+ }
76
+ const nowMs = options.now === undefined
77
+ ? Date.now()
78
+ : typeof options.now === "number"
79
+ ? options.now
80
+ : options.now.getTime();
81
+ const now = Math.floor(nowMs / 1000);
82
+ const ts = Number(timestamp);
83
+ if (ts < now - tolerance) {
84
+ throw new WebhookVerificationError("Webhook timestamp is too old");
85
+ }
86
+ if (ts > now + tolerance) {
87
+ throw new WebhookVerificationError("Webhook timestamp is too far in the future");
88
+ }
89
+ }
31
90
  /**
32
- * Validate a webhook signature.
91
+ * Validate a Standard Webhooks signature.
33
92
  *
34
- * Supports both Standard Webhooks format (v1,base64_signature) and legacy format (hex).
93
+ * Mailhook signs `${webhookId}.${timestamp}.${payload}` with HMAC-SHA256
94
+ * keyed with the base64-decoded webhook secret and sends it as
95
+ * `v1,<base64 signature>` in the `webhook-signature` header.
35
96
  *
36
- * @param payload - The raw webhook payload
37
- * @param signature - The signature from the webhook headers (Webhook-Signature or X-Webhook-Signature)
38
- * @param secret - The webhook secret (may be base64 encoded for Standard Webhooks)
39
- * @param timestamp - The timestamp from Webhook-Timestamp header (for Standard Webhooks)
40
- * @param webhookId - The webhook ID from Webhook-Id header (for Standard Webhooks)
41
- * @returns True if the signature is valid, false otherwise
97
+ * @param payload - The raw webhook request body, exactly as received
98
+ * @param signature - The `webhook-signature` header. It may contain several
99
+ * space separated `v1,<base64>` signatures; any valid one is accepted.
100
+ * @param secret - The webhook secret, `whsec_<base64>` or bare base64
101
+ * @param timestamp - The `webhook-timestamp` header (Unix seconds)
102
+ * @param webhookId - The `webhook-id` header
103
+ * @param options - Timestamp tolerance (default 300 seconds) and clock override
104
+ * @returns True if the signature is valid and the timestamp is within the
105
+ * tolerance, false otherwise
106
+ * @throws Error if the secret is not valid base64
42
107
  */
43
- export function validateWebhookSignature(payload, signature, secret, timestamp, webhookId) {
44
- // Standard Webhooks format
45
- if (!timestamp || !webhookId) {
108
+ export function validateWebhookSignature(payload, signature, secret, timestamp, webhookId, options = {}) {
109
+ if (!timestamp || !webhookId || !signature) {
46
110
  return false;
47
111
  }
48
- // Convert payload to Buffer if it's a string
49
- const payloadBuffer = typeof payload === "string" ? Buffer.from(payload, "utf-8") : payload;
50
- // Try to decode the secret as base64 first, falling back to raw if it fails
51
- let decodedSecret;
52
- if (secret.startsWith("whsec_")) {
53
- secret = secret.slice(6);
54
- }
112
+ const decodedSecret = decodeSecret(secret);
55
113
  try {
56
- decodedSecret = Buffer.from(secret, "base64");
114
+ checkTimestamp(timestamp, options);
57
115
  }
58
116
  catch {
59
- decodedSecret = Buffer.from(secret, "utf-8");
117
+ return false;
60
118
  }
61
- // Create the signed content (webhook_id.timestamp.payload)
62
- const signedContent = `${webhookId}.${timestamp}.${payloadBuffer.toString("utf-8")}`;
63
- // Generate HMAC-SHA256
119
+ const payloadBuffer = typeof payload === "string" ? Buffer.from(payload, "utf-8") : payload;
120
+ const signedContent = Buffer.concat([
121
+ Buffer.from(`${webhookId}.${timestamp}.`, "utf-8"),
122
+ payloadBuffer,
123
+ ]);
64
124
  const expectedSignature = crypto
65
125
  .createHmac("sha256", decodedSecret)
66
126
  .update(signedContent)
67
127
  .digest();
68
- // Check each versioned signature
69
- const signatures = signature.split(" ");
70
- for (const versionedSignature of signatures) {
71
- const pieces = versionedSignature.split(",");
72
- if (pieces.length !== 2) {
128
+ for (const versionedSignature of signature.split(" ")) {
129
+ const comma = versionedSignature.indexOf(",");
130
+ if (comma === -1) {
73
131
  continue;
74
132
  }
75
- const [version, b64Signature] = pieces;
133
+ const version = versionedSignature.slice(0, comma);
76
134
  if (version !== "v1") {
77
135
  continue;
78
136
  }
79
- try {
80
- const actualSignature = Buffer.from(b64Signature, "base64");
81
- if (crypto.timingSafeEqual(actualSignature, expectedSignature)) {
82
- return true;
83
- }
137
+ const actualSignature = decodeBase64Strict(versionedSignature.slice(comma + 1));
138
+ if (actualSignature &&
139
+ actualSignature.length === expectedSignature.length &&
140
+ crypto.timingSafeEqual(actualSignature, expectedSignature)) {
141
+ return true;
84
142
  }
85
- catch { }
86
143
  }
87
144
  return false;
88
145
  }
89
146
  /**
90
- * Verify webhook signature and parse the event.
147
+ * Verify a webhook delivery and parse the event.
91
148
  *
92
- * This is a convenience function that combines signature validation
93
- * and event parsing.
149
+ * The signature, timestamp and webhook id are taken from the explicit
150
+ * arguments or, if not given, from `headers` (looked up case-insensitively).
94
151
  *
95
- * @param payload - The raw webhook payload
96
- * @param secret - The webhook secret
97
- * @param signature - The signature from the webhook headers
98
- * @param timestamp - The timestamp from webhook-timestamp header
99
- * @param webhookId - The webhook id from webhook-id header
100
- * @param headers - A mapping of http headers (case insensitive) as alternative to signature, timestamp and webhookId
152
+ * @param payload - The raw webhook request body, exactly as received
153
+ * @param secret - The webhook secret, `whsec_<base64>` or bare base64
154
+ * @param signature - The `webhook-signature` header
155
+ * @param timestamp - The `webhook-timestamp` header
156
+ * @param webhookId - The `webhook-id` header
157
+ * @param headers - The request headers, as an alternative to signature, timestamp and webhookId
158
+ * @param options - Timestamp tolerance (default 300 seconds) and clock override
101
159
  * @returns The parsed webhook event
102
- * @throws Error if the signature is invalid or payload cannot be parsed
160
+ * @throws WebhookVerificationError if a header is missing, the timestamp is
161
+ * outside the tolerance or the signature is invalid
162
+ * @throws Error if the secret is not valid base64 or the payload cannot be parsed
103
163
  */
104
- export function verifyAndParseWebhook(payload, secret, signature, timestamp, webhookId, headers) {
164
+ export function verifyAndParseWebhook(payload, secret, signature, timestamp, webhookId, headers, options = {}) {
105
165
  // Extract from headers if provided
106
166
  if (headers) {
107
167
  // Convert headers to lowercase for case-insensitive lookup
@@ -114,16 +174,19 @@ export function verifyAndParseWebhook(payload, secret, signature, timestamp, web
114
174
  webhookId = webhookId || lowerHeaders["webhook-id"];
115
175
  }
116
176
  if (!signature) {
117
- throw new Error("Signature is required");
177
+ throw new WebhookVerificationError("Signature is required");
118
178
  }
119
179
  if (!timestamp) {
120
- throw new Error("Timestamp is required");
180
+ throw new WebhookVerificationError("Timestamp is required");
121
181
  }
122
182
  if (!webhookId) {
123
- throw new Error("Webhook ID is required");
183
+ throw new WebhookVerificationError("Webhook ID is required");
124
184
  }
125
- if (!validateWebhookSignature(payload, signature, secret, timestamp, webhookId)) {
126
- throw new Error("Invalid webhook signature");
185
+ checkTimestamp(timestamp, options);
186
+ if (!validateWebhookSignature(payload, signature, secret, timestamp, webhookId, {
187
+ toleranceSeconds: null,
188
+ })) {
189
+ throw new WebhookVerificationError("Invalid webhook signature");
127
190
  }
128
191
  return parseWebhookEvent(payload);
129
192
  }
@@ -1 +1 @@
1
- {"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/mailhook/webhook.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/mailhook/webhook.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@earendil-works/mailhook",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "TypeScript SDK for the Mailhook API",
5
5
  "type": "module",
6
6
  "author": "Armin Ronacher <armin.ronacher@active-4.com>",
@@ -27,8 +27,6 @@
27
27
  "exports": {
28
28
  ".": {
29
29
  "types": "./dist/index.d.ts",
30
- "import": "./dist/index.js",
31
- "require": "./dist/index.js",
32
30
  "default": "./dist/index.js"
33
31
  },
34
32
  "./package.json": "./package.json"
@@ -46,19 +44,18 @@
46
44
  "generate": "cd ../generator && uv run main.py typescript",
47
45
  "dev": "tsc -p tsconfig.json --watch",
48
46
  "lint": "biome check .",
49
- "lint:fix": "biome check --write --unsafe .",
50
- "format": "prettier --write \"src/**/*.{ts,tsx,json,md}\"",
51
- "format:check": "prettier --check \"src/**/*.{ts,tsx,json,md}\"",
52
- "typecheck": "tsc -p tsconfig.json --noEmit",
47
+ "lint:fix": "biome check --write .",
48
+ "format": "biome format --write .",
49
+ "typecheck": "tsc -p tsconfig.check.json",
50
+ "test": "node --test test/*.test.ts",
53
51
  "prepublishOnly": "pnpm run generate && pnpm run build"
54
52
  },
55
53
  "engines": {
56
- "node": ">=18.0.0"
54
+ "node": ">=20.19.0"
57
55
  },
58
56
  "devDependencies": {
59
57
  "@biomejs/biome": "2.3.9",
60
- "@types/node": "^20.0.0",
61
- "prettier": "^3.0.0",
62
- "typescript": "^5.9.0"
58
+ "@types/node": "^20.19.43",
59
+ "typescript": "^5.9.3"
63
60
  }
64
61
  }
@@ -1,2 +0,0 @@
1
- export { Mailhook } from "./_internals/base-client.ts";
2
- //# sourceMappingURL=client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/mailhook/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC"}
@@ -1,2 +0,0 @@
1
- export { Mailhook } from "./_internals/base-client.js";
2
- //# sourceMappingURL=client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/mailhook/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC"}