hooklens 0.2.0 → 1.0.1
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/README.md +33 -120
- package/dist/index.js +589 -238
- package/dist/index.js.map +1 -1
- package/package.json +10 -3
package/README.md
CHANGED
|
@@ -1,155 +1,68 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
+
<img src="https://ilia01.github.io/hooklens/logo.svg" alt="HookLens logo" width="88" height="88">
|
|
4
|
+
|
|
3
5
|
# HookLens
|
|
4
6
|
|
|
5
|
-
**
|
|
7
|
+
**Debug webhook signature failures locally.**
|
|
8
|
+
|
|
9
|
+
Figure out why webhook signature verification failed before your framework hides the evidence.
|
|
10
|
+
|
|
11
|
+
[Documentation](https://ilia01.github.io/hooklens/) · [npm](https://www.npmjs.com/package/hooklens) · [Latest release](https://github.com/Ilia01/hooklens/releases/latest) · [Contributing](./CONTRIBUTING.md)
|
|
6
12
|
|
|
7
13
|
[](LICENSE)
|
|
8
14
|
[](https://github.com/Ilia01/hooklens/actions/workflows/ci.yml)
|
|
9
15
|
|
|
10
16
|
</div>
|
|
11
17
|
|
|
12
|
-
> [!WARNING]
|
|
13
|
-
> HookLens is under active development. Expect changes as more providers and debugging workflows are added.
|
|
14
|
-
|
|
15
18
|
---
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
HookLens is a local CLI for the annoying part of webhook debugging:
|
|
21
|
+
the delivery reached your app, verification still failed, and your framework already changed the body you needed to inspect.
|
|
18
22
|
|
|
19
|
-
|
|
23
|
+
It captures the incoming request before parsing, verifies it locally, stores the event, and lets you replay the exact delivery after you fix your app.
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
hooklens listen --verify stripe --secret whsec_xxx --forward-to http://localhost:3000/webhook
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
When a webhook arrives, HookLens:
|
|
28
|
-
|
|
29
|
-
1. Captures the raw body before any framework parses it
|
|
30
|
-
2. Verifies the provider signature and prints PASS or FAIL with a reason
|
|
31
|
-
3. Stores the event locally for replay
|
|
32
|
-
4. Forwards it to your app
|
|
33
|
-
|
|
34
|
-
Something break? Check what came in and replay it:
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
hooklens list
|
|
38
|
-
hooklens replay evt_abc123 --to http://localhost:3000/webhook
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
> [!IMPORTANT]
|
|
42
|
-
> HookLens is **not** a tunnel. You still need [ngrok](https://ngrok.com), [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/), or a similar tool to expose your local server to the internet. HookLens handles what happens after the request arrives.
|
|
43
|
-
|
|
44
|
-
## Why signature verification breaks
|
|
45
|
-
|
|
46
|
-
This is the problem HookLens exists to solve.
|
|
47
|
-
|
|
48
|
-
Webhook providers (Stripe, Paddle, GitHub, etc.) sign every request using the raw body. Your server is supposed to recompute that signature and compare. Simple in theory, but:
|
|
49
|
-
|
|
50
|
-
- **Express** parses the body into JSON before your route handler sees it. When you `JSON.stringify()` it back, key ordering or whitespace changes. Different string = different hash = verification fails.
|
|
51
|
-
- **Next.js** and **Fastify** do the same thing in different ways.
|
|
52
|
-
- The error you get? `"Webhook signature verification failed."` -- thanks for nothing.
|
|
53
|
-
|
|
54
|
-
HookLens intercepts the request at the HTTP level using `node:http` directly, before any framework touches the body. It verifies against the actual bytes that arrived over the wire, and when it fails, it tells you which of the 5 possible failure modes you hit:
|
|
55
|
-
|
|
56
|
-
| Failure | What HookLens tells you |
|
|
57
|
-
| ----------------- | ----------------------------------------------------------------------------------------------------- |
|
|
58
|
-
| Missing header | `stripe-signature header not found. Is this actually from Stripe?` |
|
|
59
|
-
| Wrong secret | `Signature mismatch. Check your webhook secret matches the Stripe dashboard.` |
|
|
60
|
-
| Expired timestamp | `Timestamp is 47 minutes old. Event expired or your clock is drifting.` |
|
|
61
|
-
| Body mutated | `Signature mismatch with correct secret. Body was likely parsed and re-serialized by your framework.` |
|
|
62
|
-
| Malformed header | `stripe-signature header is malformed. Expected format: t=timestamp,v1=signature` |
|
|
25
|
+
<p align="center">
|
|
26
|
+
<img src="https://ilia01.github.io/hooklens/hooklens-demo.gif" alt="HookLens demo showing capture, verification, listing, and replay from the terminal" width="980">
|
|
27
|
+
</p>
|
|
63
28
|
|
|
64
29
|
## Install
|
|
65
30
|
|
|
66
|
-
**Requires Node.js 24 or newer
|
|
31
|
+
**Requires Node.js 24 or newer**.
|
|
67
32
|
|
|
68
33
|
```bash
|
|
69
34
|
npm install -g hooklens
|
|
70
35
|
```
|
|
71
36
|
|
|
72
|
-
##
|
|
73
|
-
|
|
74
|
-
If you want to run HookLens from source or contribute to it:
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
git clone https://github.com/Ilia01/hooklens.git
|
|
78
|
-
cd hooklens
|
|
79
|
-
npm install
|
|
80
|
-
npm run build
|
|
81
|
-
npm link
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## Commands
|
|
85
|
-
|
|
86
|
-
| Command | Description |
|
|
87
|
-
| ---------------------- | ------------------------ |
|
|
88
|
-
| `hooklens listen` | Start receiving webhooks |
|
|
89
|
-
| `hooklens list` | Show stored events |
|
|
90
|
-
| `hooklens replay <id>` | Resend a stored event |
|
|
91
|
-
|
|
92
|
-
### `hooklens listen`
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
hooklens listen --port 4400 --verify stripe --secret whsec_xxx --forward-to http://localhost:3000/webhook
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
| Flag | Default | Description |
|
|
99
|
-
| --------------------- | ------- | ------------------------------------- |
|
|
100
|
-
| `-p, --port <port>` | `4400` | Port to listen on |
|
|
101
|
-
| `--verify <provider>` | -- | Verify signatures (`stripe`) |
|
|
102
|
-
| `--secret <secret>` | -- | Webhook signing secret |
|
|
103
|
-
| `--forward-to <url>` | -- | Forward received webhooks to this URL |
|
|
104
|
-
|
|
105
|
-
### `hooklens list`
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
hooklens list --limit 10
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
| Flag | Default | Description |
|
|
112
|
-
| --------------------- | ------- | ------------------------ |
|
|
113
|
-
| `-n, --limit <count>` | `20` | Number of events to show |
|
|
114
|
-
|
|
115
|
-
### `hooklens replay`
|
|
37
|
+
## The loop
|
|
116
38
|
|
|
117
39
|
```bash
|
|
40
|
+
hooklens listen --verify github --secret ghsecret_xxx
|
|
41
|
+
hooklens list
|
|
42
|
+
hooklens inspect evt_abc123
|
|
118
43
|
hooklens replay evt_abc123 --to http://localhost:3000/webhook
|
|
119
44
|
```
|
|
120
45
|
|
|
121
|
-
|
|
122
|
-
| ------------ | ------------------------------- | ------------------------------- |
|
|
123
|
-
| `--to <url>` | `http://localhost:3000/webhook` | Target URL to send the event to |
|
|
124
|
-
|
|
125
|
-
## Supported providers
|
|
126
|
-
|
|
127
|
-
- **Stripe** -- full signature verification with detailed failure messages
|
|
128
|
-
|
|
129
|
-
More providers will be added based on demand. [Open an issue](https://github.com/Ilia01/hooklens/issues) to request one.
|
|
46
|
+
Point your provider CLI, tunnel, or webhook source at `http://127.0.0.1:4400`.
|
|
130
47
|
|
|
131
|
-
|
|
48
|
+
Use HookLens when:
|
|
132
49
|
|
|
133
|
-
|
|
50
|
+
- the request reached your machine, but signature verification failed
|
|
51
|
+
- your framework parsed or re-serialized the body before verification
|
|
52
|
+
- you need the exact stored request, not a vague error line
|
|
53
|
+
- you want to replay the same event after changing middleware, secrets, or handler logic
|
|
134
54
|
|
|
135
|
-
|
|
136
|
-
git clone https://github.com/Ilia01/hooklens.git
|
|
137
|
-
cd hooklens
|
|
138
|
-
npm install
|
|
139
|
-
npm run dev
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
`npm run dev` watches for changes and rebuilds automatically. You can test your changes by running `hooklens` commands directly against the local build.
|
|
55
|
+
It is not a tunnel, a hosted webhook inbox, or a replacement for provider delivery tooling.
|
|
143
56
|
|
|
144
|
-
|
|
57
|
+
## Read Next
|
|
145
58
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
59
|
+
- [Getting Started](https://ilia01.github.io/hooklens/getting-started) for installation and first capture
|
|
60
|
+
- [Commands](https://ilia01.github.io/hooklens/commands/) for the CLI reference
|
|
61
|
+
- [Verification](https://ilia01.github.io/hooklens/verification/) for failure codes and provider behavior
|
|
62
|
+
- [Stripe signature failures](https://ilia01.github.io/hooklens/verification/stripe-signature-failures)
|
|
63
|
+
- [GitHub signature mismatches](https://ilia01.github.io/hooklens/verification/github-signature-mismatch)
|
|
64
|
+
- [Raw body mutation](https://ilia01.github.io/hooklens/verification/raw-body-mutation)
|
|
65
|
+
- [Contributing](./CONTRIBUTING.md)
|
|
153
66
|
|
|
154
67
|
## License
|
|
155
68
|
|