Skip to content
This repository was archived by the owner on Jan 23, 2021. It is now read-only.

Commit 5c5b576

Browse files
Support to verify Webhook signatures
- Add `signingSecret` configuration to `config.sample.js` - Add verification path to Webhooks express server to verify signatures - Add documentation for `signingSecret` - Update some outdated, vulnerable dependencies
1 parent 823a618 commit 5c5b576

File tree

4 files changed

+72
-54
lines changed

4 files changed

+72
-54
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ Webhooks require a public URL that Stripe will ping to notify the monitor of new
3131

3232
If you have a [__Basic__](https://ngrok.com/pricing) ngrok subscription, you can specify a custom subdomain that will stay reserved for your account.
3333

34+
#### Optional: Verify Webhooks are signed
35+
[Stripe can optionally sign Webhook events to your endpoints](https://stripe.com/docs/webhooks/signatures). If you'd like the Webhook Monitor to verify these for you, simply modify the `signingSecret` value in `config.js` with the endpoint-specific signing secret key found at the bottom of the Webhook details page.
36+
37+
Unverified Webhooks will return a `400` response to Stripe, and log an error to your console.
38+
3439
### Start receiving changes
3540

3641
To start the monitor:

config.sample.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ module.exports = {
44
port: 4000,
55
stripe: {
66
// Include your Stripe secret key here
7-
secretKey: 'YOUR_STRIPE_SECRET_KEY'
7+
secretKey: 'YOUR_STRIPE_SECRET_KEY',
8+
signingSecret: null
89
},
910
/*
1011
Stripe needs a public URL for our server that it can ping with new events.

package-lock.json

Lines changed: 44 additions & 50 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,32 @@ monitor.get("/recent-events", async (req, res) => {
4949
const webhooks = express();
5050
const webhooksPort = config.port + 1;
5151

52-
webhooks.use(bodyParser.json());
5352
webhooks.listen(webhooksPort, () => {
5453
console.log(`Listening for webhooks: http://localhost:${webhooksPort}`);
5554
});
5655

5756
// Provides an endpoint to receive webhooks
58-
webhooks.post("/", async (req, res) => {
59-
let event = req.body;
57+
webhooks.post("/", bodyParser.raw({ type: "application/json" }), async (req, res) => {
58+
let event;
59+
60+
// Check if signing secret has been set
61+
if (config.stripe.signingSecret) {
62+
const sig = req.headers['stripe-signature'];
63+
64+
try {
65+
event = stripe.webhooks.constructEvent(req.body, sig, config.stripe.signingSecret);
66+
} catch (err) {
67+
console.log(
68+
chalk.red(`Failed to verify webhook signature: ${err.message}`)
69+
);
70+
res.sendStatus(400);
71+
return;
72+
}
73+
} else {
74+
// Signing secret is not set, just pass through
75+
event = req.body;
76+
}
77+
6078
// Send a notification that we have a new event
6179
// Here we're using Socket.io, but server-sent events or another mechanism can be used.
6280
io.emit("event", event);

0 commit comments

Comments
 (0)