@hookflo/tern 1.0.1 → 1.0.3

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.
package/dist/test.js CHANGED
@@ -1,102 +1,176 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.runAllTests = runAllTests;
4
- exports.testGitHubWebhook = testGitHubWebhook;
5
- exports.testTokenBasedWebhook = testTokenBasedWebhook;
6
- exports.testPlatformDetection = testPlatformDetection;
7
- exports.testCustomSignature = testCustomSignature;
3
+ exports.runTests = runTests;
4
+ const crypto_1 = require("crypto");
8
5
  const index_1 = require("./index");
9
- const utils_1 = require("./utils");
10
- // Mock request for testing
11
- function createMockRequest(headers, body = '{"test": "data"}') {
12
- return new Request('http://localhost/webhook', {
6
+ // Test data
7
+ const testSecret = 'whsec_test_secret_key_12345';
8
+ const testBody = JSON.stringify({ event: 'test', data: { id: '123' } });
9
+ // Helper function to create a mock request
10
+ function createMockRequest(headers, body = testBody) {
11
+ return new Request('https://example.com/webhook', {
13
12
  method: 'POST',
14
13
  headers,
15
14
  body,
16
15
  });
17
16
  }
18
- // Test GitHub webhook
19
- async function testGitHubWebhook() {
20
- console.log('Testing GitHub webhook...');
21
- const request = createMockRequest({
22
- 'x-hub-signature-256': 'sha256=abc123',
23
- 'content-type': 'application/json',
24
- });
25
- const result = await index_1.WebhookVerificationService.verifyWithPlatformConfig(request, 'github', 'test-secret', 300);
26
- console.log('GitHub result:', result);
27
- return result;
28
- }
29
- // Test token-based webhook (Supabase style)
30
- async function testTokenBasedWebhook() {
31
- console.log('Testing token-based webhook...');
32
- const request = createMockRequest({
33
- 'x-webhook-id': 'test-webhook-id',
34
- 'x-webhook-token': 'test-webhook-token',
35
- 'content-type': 'application/json',
36
- });
37
- const result = await index_1.WebhookVerificationService.verifyTokenBased(request, 'test-webhook-id', 'test-webhook-token');
38
- console.log('Token-based result:', result);
39
- return result;
17
+ // Helper function to create Stripe signature
18
+ function createStripeSignature(body, secret, timestamp) {
19
+ const signedPayload = `${timestamp}.${body}`;
20
+ const hmac = (0, crypto_1.createHmac)('sha256', secret);
21
+ hmac.update(signedPayload);
22
+ const signature = hmac.digest('hex');
23
+ return `t=${timestamp},v1=${signature}`;
40
24
  }
41
- // Test platform detection
42
- function testPlatformDetection() {
43
- console.log('Testing platform detection...');
44
- const testCases = [
45
- {
46
- name: 'GitHub',
47
- headers: { 'x-hub-signature-256': 'sha256=abc123' },
48
- },
49
- {
50
- name: 'Stripe',
51
- headers: { 'stripe-signature': 't=1234567890,v1=abc123' },
52
- },
53
- {
54
- name: 'Clerk',
55
- headers: { 'svix-signature': 'v1,abc123' },
56
- },
57
- {
58
- name: 'Supabase',
59
- headers: { 'x-webhook-token': 'token123' },
60
- },
61
- ];
62
- for (const testCase of testCases) {
63
- const request = createMockRequest((0, utils_1.cleanHeaders)(testCase.headers));
64
- const detectedPlatform = (0, utils_1.detectPlatformFromHeaders)(request.headers);
65
- console.log(`${testCase.name}: ${detectedPlatform}`);
66
- }
25
+ // Helper function to create GitHub signature
26
+ function createGitHubSignature(body, secret) {
27
+ const hmac = (0, crypto_1.createHmac)('sha256', secret);
28
+ hmac.update(body);
29
+ return `sha256=${hmac.digest('hex')}`;
67
30
  }
68
- // Test custom signature configuration
69
- async function testCustomSignature() {
70
- console.log('Testing custom signature...');
71
- const request = createMockRequest({
72
- 'x-custom-signature': 'sha256=abc123',
73
- 'content-type': 'application/json',
74
- });
75
- const result = await index_1.WebhookVerificationService.verify(request, {
76
- platform: 'custom',
77
- secret: 'custom-secret',
78
- signatureConfig: {
79
- algorithm: 'hmac-sha256',
80
- headerName: 'x-custom-signature',
81
- headerFormat: 'prefixed',
82
- prefix: 'sha256=',
83
- payloadFormat: 'raw',
84
- },
85
- });
86
- console.log('Custom signature result:', result);
87
- return result;
31
+ // Helper function to create Clerk signature
32
+ function createClerkSignature(body, secret, id, timestamp) {
33
+ const signedContent = `${id}.${timestamp}.${body}`;
34
+ const secretBytes = new Uint8Array(Buffer.from(secret.split('_')[1], 'base64'));
35
+ const hmac = (0, crypto_1.createHmac)('sha256', secretBytes);
36
+ hmac.update(signedContent);
37
+ return `v1,${hmac.digest('base64')}`;
88
38
  }
89
- // Run all tests
90
- async function runAllTests() {
91
- console.log('šŸš€ Running Webhook Verifier Tests\n');
39
+ async function runTests() {
40
+ console.log('🧪 Running Webhook Verification Tests...\n');
41
+ // Test 1: Stripe Webhook
42
+ console.log('1. Testing Stripe Webhook...');
43
+ try {
44
+ const timestamp = Math.floor(Date.now() / 1000);
45
+ const stripeSignature = createStripeSignature(testBody, testSecret, timestamp);
46
+ const stripeRequest = createMockRequest({
47
+ 'stripe-signature': stripeSignature,
48
+ 'content-type': 'application/json',
49
+ });
50
+ const stripeResult = await index_1.WebhookVerificationService.verifyWithPlatformConfig(stripeRequest, 'stripe', testSecret);
51
+ console.log(' āœ… Stripe:', stripeResult.isValid ? 'PASSED' : 'FAILED');
52
+ if (!stripeResult.isValid) {
53
+ console.log(' āŒ Error:', stripeResult.error);
54
+ }
55
+ }
56
+ catch (error) {
57
+ console.log(' āŒ Stripe test failed:', error);
58
+ }
59
+ // Test 2: GitHub Webhook
60
+ console.log('\n2. Testing GitHub Webhook...');
61
+ try {
62
+ const githubSignature = createGitHubSignature(testBody, testSecret);
63
+ const githubRequest = createMockRequest({
64
+ 'x-hub-signature-256': githubSignature,
65
+ 'x-github-event': 'push',
66
+ 'x-github-delivery': 'test-delivery-id',
67
+ 'content-type': 'application/json',
68
+ });
69
+ const githubResult = await index_1.WebhookVerificationService.verifyWithPlatformConfig(githubRequest, 'github', testSecret);
70
+ console.log(' āœ… GitHub:', githubResult.isValid ? 'PASSED' : 'FAILED');
71
+ if (!githubResult.isValid) {
72
+ console.log(' āŒ Error:', githubResult.error);
73
+ }
74
+ }
75
+ catch (error) {
76
+ console.log(' āŒ GitHub test failed:', error);
77
+ }
78
+ // Test 3: Clerk Webhook
79
+ console.log('\n3. Testing Clerk Webhook...');
92
80
  try {
93
- await testGitHubWebhook();
94
- await testTokenBasedWebhook();
95
- testPlatformDetection();
96
- await testCustomSignature();
97
- console.log('\nāœ… All tests completed successfully!');
81
+ // Create a proper Clerk-style secret (whsec_ + base64 encoded secret)
82
+ const base64Secret = Buffer.from(testSecret).toString('base64');
83
+ const clerkSecret = `whsec_${base64Secret}`;
84
+ const id = 'test-id-123';
85
+ const timestamp = Math.floor(Date.now() / 1000);
86
+ const clerkSignature = createClerkSignature(testBody, clerkSecret, id, timestamp);
87
+ const clerkRequest = createMockRequest({
88
+ 'svix-signature': clerkSignature,
89
+ 'svix-id': id,
90
+ 'svix-timestamp': timestamp.toString(),
91
+ 'content-type': 'application/json',
92
+ });
93
+ const clerkResult = await index_1.WebhookVerificationService.verifyWithPlatformConfig(clerkRequest, 'clerk', clerkSecret);
94
+ console.log(' āœ… Clerk:', clerkResult.isValid ? 'PASSED' : 'FAILED');
95
+ if (!clerkResult.isValid) {
96
+ console.log(' āŒ Error:', clerkResult.error);
97
+ }
98
98
  }
99
99
  catch (error) {
100
- console.error('\nāŒ Test failed:', error);
100
+ console.log(' āŒ Clerk test failed:', error);
101
+ }
102
+ // Test 4: Standard HMAC-SHA256 (Generic)
103
+ console.log('\n4. Testing Standard HMAC-SHA256...');
104
+ try {
105
+ const hmac = (0, crypto_1.createHmac)('sha256', testSecret);
106
+ hmac.update(testBody);
107
+ const signature = hmac.digest('hex');
108
+ const genericRequest = createMockRequest({
109
+ 'x-webhook-signature': signature,
110
+ 'content-type': 'application/json',
111
+ });
112
+ const genericResult = await index_1.WebhookVerificationService.verifyWithPlatformConfig(genericRequest, 'unknown', testSecret);
113
+ console.log(' āœ… Generic HMAC-SHA256:', genericResult.isValid ? 'PASSED' : 'FAILED');
114
+ if (!genericResult.isValid) {
115
+ console.log(' āŒ Error:', genericResult.error);
116
+ }
101
117
  }
118
+ catch (error) {
119
+ console.log(' āŒ Generic test failed:', error);
120
+ }
121
+ // Test 5: Token-based (Supabase)
122
+ console.log('\n5. Testing Token-based Authentication...');
123
+ try {
124
+ const webhookId = 'test-webhook-id';
125
+ const webhookToken = 'test-webhook-token';
126
+ const tokenRequest = createMockRequest({
127
+ 'x-webhook-id': webhookId,
128
+ 'x-webhook-token': webhookToken,
129
+ 'content-type': 'application/json',
130
+ });
131
+ const tokenResult = await index_1.WebhookVerificationService.verifyTokenBased(tokenRequest, webhookId, webhookToken);
132
+ console.log(' āœ… Token-based:', tokenResult.isValid ? 'PASSED' : 'FAILED');
133
+ if (!tokenResult.isValid) {
134
+ console.log(' āŒ Error:', tokenResult.error);
135
+ }
136
+ }
137
+ catch (error) {
138
+ console.log(' āŒ Token-based test failed:', error);
139
+ }
140
+ // Test 6: Invalid signatures
141
+ console.log('\n6. Testing Invalid Signatures...');
142
+ try {
143
+ const invalidRequest = createMockRequest({
144
+ 'stripe-signature': 't=1234567890,v1=invalid_signature',
145
+ 'content-type': 'application/json',
146
+ });
147
+ const invalidResult = await index_1.WebhookVerificationService.verifyWithPlatformConfig(invalidRequest, 'stripe', testSecret);
148
+ console.log(' āœ… Invalid signature correctly rejected:', !invalidResult.isValid ? 'PASSED' : 'FAILED');
149
+ if (invalidResult.isValid) {
150
+ console.log(' āŒ Should have been rejected');
151
+ }
152
+ }
153
+ catch (error) {
154
+ console.log(' āŒ Invalid signature test failed:', error);
155
+ }
156
+ // Test 7: Missing headers
157
+ console.log('\n7. Testing Missing Headers...');
158
+ try {
159
+ const missingHeaderRequest = createMockRequest({
160
+ 'content-type': 'application/json',
161
+ });
162
+ const missingHeaderResult = await index_1.WebhookVerificationService.verifyWithPlatformConfig(missingHeaderRequest, 'stripe', testSecret);
163
+ console.log(' āœ… Missing headers correctly rejected:', !missingHeaderResult.isValid ? 'PASSED' : 'FAILED');
164
+ if (missingHeaderResult.isValid) {
165
+ console.log(' āŒ Should have been rejected');
166
+ }
167
+ }
168
+ catch (error) {
169
+ console.log(' āŒ Missing headers test failed:', error);
170
+ }
171
+ console.log('\nšŸŽ‰ All tests completed!');
172
+ }
173
+ // Run tests if this file is executed directly
174
+ if (require.main === module) {
175
+ runTests().catch(console.error);
102
176
  }
@@ -1,22 +1,30 @@
1
1
  import { WebhookVerifier } from "./base";
2
- import { WebhookVerificationResult, SignatureConfig } from "../types";
2
+ import { WebhookVerificationResult, SignatureConfig, WebhookPlatform } from "../types";
3
3
  export declare abstract class AlgorithmBasedVerifier extends WebhookVerifier {
4
4
  protected config: SignatureConfig;
5
- constructor(secret: string, config: SignatureConfig, toleranceInSeconds?: number);
5
+ protected platform: WebhookPlatform;
6
+ constructor(secret: string, config: SignatureConfig, platform: WebhookPlatform, toleranceInSeconds?: number);
6
7
  abstract verify(request: Request): Promise<WebhookVerificationResult>;
7
8
  protected extractSignature(request: Request): string | null;
8
9
  protected extractTimestamp(request: Request): number | null;
9
- protected formatPayload(rawBody: string, timestamp?: number | null): string;
10
+ protected extractTimestampFromSignature(request: Request): number | null;
11
+ protected formatPayload(rawBody: string, request: Request): string;
12
+ protected formatCustomPayload(rawBody: string, request: Request): string;
10
13
  protected verifyHMAC(payload: string, signature: string, algorithm?: string): boolean;
11
14
  protected verifyHMACWithPrefix(payload: string, signature: string, algorithm?: string): boolean;
15
+ protected verifyHMACWithBase64(payload: string, signature: string, algorithm?: string): boolean;
16
+ protected extractMetadata(request: Request): Record<string, any>;
12
17
  }
13
- export declare class HMACSHA256Verifier extends AlgorithmBasedVerifier {
18
+ export declare class GenericHMACVerifier extends AlgorithmBasedVerifier {
14
19
  verify(request: Request): Promise<WebhookVerificationResult>;
15
20
  }
16
- export declare class HMACSHA1Verifier extends AlgorithmBasedVerifier {
17
- verify(request: Request): Promise<WebhookVerificationResult>;
21
+ export declare class HMACSHA256Verifier extends GenericHMACVerifier {
22
+ constructor(secret: string, config: SignatureConfig, platform?: WebhookPlatform, toleranceInSeconds?: number);
18
23
  }
19
- export declare class HMACSHA512Verifier extends AlgorithmBasedVerifier {
20
- verify(request: Request): Promise<WebhookVerificationResult>;
24
+ export declare class HMACSHA1Verifier extends GenericHMACVerifier {
25
+ constructor(secret: string, config: SignatureConfig, platform?: WebhookPlatform, toleranceInSeconds?: number);
26
+ }
27
+ export declare class HMACSHA512Verifier extends GenericHMACVerifier {
28
+ constructor(secret: string, config: SignatureConfig, platform?: WebhookPlatform, toleranceInSeconds?: number);
21
29
  }
22
- export declare function createAlgorithmVerifier(secret: string, config: SignatureConfig, toleranceInSeconds?: number): AlgorithmBasedVerifier;
30
+ export declare function createAlgorithmVerifier(secret: string, config: SignatureConfig, platform?: WebhookPlatform, toleranceInSeconds?: number): AlgorithmBasedVerifier;