MCPcopy Create free account
hub / github.com/GoogleCloudPlatform/nodejs-docs-samples / verifyWebhook

Function verifyWebhook

functions/slack/index.js:95–139  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

93 * @param {string} req.rawBody Raw body of webhook request to check signature against.
94 */
95const verifyWebhook = req => {
96 const signingSecret = process.env.SLACK_SECRET;
97 const requestSignature = req.headers['x-slack-signature'];
98 const requestTimestamp = req.headers['x-slack-request-timestamp'];
99 const requestBody = req.rawBody;
100
101 if (!requestSignature || !requestTimestamp) {
102 const err = new Error('Missing Slack validation headers.');
103 err.code = 400;
104 throw err;
105 }
106
107 if (!signingSecret) {
108 const err = new Error(
109 'Server configuration error: SLACK_SECRET is missing.'
110 );
111 err.code = 500;
112 throw err;
113 }
114
115 // Prevent replay attacks by verifying the timestamp is recent
116 const now = Math.floor(Date.now() / 1000);
117 if (Math.abs(now - Number(requestTimestamp)) > 60 * 5) {
118 const err = new Error('Slack request timestamp is too old.');
119 err.code = 401;
120 throw err;
121 }
122
123 const hmac = crypto.createHmac('sha256', signingSecret);
124 hmac.update('v0:' + requestTimestamp + ':', 'utf8');
125 hmac.update(requestBody || '');
126 const expectedSignature = 'v0=' + hmac.digest('hex');
127
128 const sigBuffer = Buffer.from(requestSignature, 'utf8');
129 const expBuffer = Buffer.from(expectedSignature, 'utf8');
130
131 if (
132 sigBuffer.length !== expBuffer.length ||
133 !crypto.timingSafeEqual(sigBuffer, expBuffer)
134 ) {
135 const err = new Error('Invalid Slack signature.');
136 err.code = 401;
137 throw err;
138 }
139};
140// [END functions_verify_webhook]
141
142// [START functions_slack_request]

Callers 1

index.jsFile · 0.85

Calls 1

updateMethod · 0.45

Tested by

no test coverage detected