|
17 | 17 | // [START functions_slack_setup] |
18 | 18 | const functions = require('@google-cloud/functions-framework'); |
19 | 19 | const google = require('@googleapis/kgsearch'); |
20 | | -const {verifyRequestSignature} = require('@slack/events-api'); |
| 20 | +const crypto = require('crypto') |
21 | 21 |
|
22 | 22 | // Get a reference to the Knowledge Graph Search component |
23 | 23 | const kgsearch = google.kgsearch('v1'); |
@@ -93,12 +93,30 @@ const formatSlackMessage = (query, response) => { |
93 | 93 | * @param {string} req.rawBody Raw body of webhook request to check signature against. |
94 | 94 | */ |
95 | 95 | const verifyWebhook = req => { |
96 | | - const signature = { |
97 | | - signingSecret: process.env.SLACK_SECRET, |
98 | | - requestSignature: req.headers['x-slack-signature'], |
99 | | - requestTimestamp: req.headers['x-slack-request-timestamp'], |
100 | | - body: req.rawBody, |
101 | | - }; |
| 96 | + const slackSigningSecret = process.env.SLACK_SECRET; |
| 97 | + const requestSignature = req.headers['x-slack-signature']; |
| 98 | + const requestTimestamp = req.headers['x-slack-request-timestamp']; |
| 99 | + |
| 100 | + if (!requestSignature || !requestTimestamp) { |
| 101 | + throw new Error('Missing slack signature or timestamp headers'); |
| 102 | + } |
| 103 | + |
| 104 | + // Prevent repeat seizures (5 minutes tolerance) |
| 105 | + const fiveMinutesAgo = Math.floor(Date.now() / 1000) - 300; |
| 106 | + if (parseInt(requestTime, 10) < fiveMinutesAgo) { |
| 107 | + throw new Error('Requested slack timestamp is too old'); |
| 108 | + } |
| 109 | + |
| 110 | + const basestring = `v0:${requestTimestamp}:${req.rawBody}`; |
| 111 | + const hmac = crypto.createHmac('sha256', slackSigningSecret); |
| 112 | + hmac.update(basestring, 'utf-8'); |
| 113 | + const digest = `v0=${hmac.digest('hex')}`; |
| 114 | + |
| 115 | + if (!crypto.timingSafeEqual(Buffer.from(digest, 'utf-8'), Buffer.from(requestSignature, 'utf8'))) { |
| 116 | + const error = new Error('slack invalid signature'); |
| 117 | + error.code = 401; |
| 118 | + throw error; |
| 119 | + } |
102 | 120 |
|
103 | 121 | // This method throws an exception if an incoming request is invalid. |
104 | 122 | verifyRequestSignature(signature); |
|
0 commit comments