Skip to content

Commit

Permalink
functions/slack: message verification - tokens -> signatures (#1562)
Browse files Browse the repository at this point in the history
* functions/slack: message verification - tokens -> signatures

* Fix lint

* Fix tests
  • Loading branch information
Ace Nassri authored Jan 10, 2020
1 parent 0ae59a9 commit b0cbf5a
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 12 deletions.
2 changes: 1 addition & 1 deletion functions/slack/config.default.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"SLACK_TOKEN": "[YOUR_SLACK_TOKEN]",
"SLACK_SECRET": "[YOUR_SLACK_SIGNING_SECRET]",
"KG_API_KEY": "[YOUR_KG_API_KEY]"
}
26 changes: 16 additions & 10 deletions functions/slack/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
// [START functions_slack_setup]
const config = require('./config.json');
const {google} = require('googleapis');
const {verifyRequestSignature} = require('@slack/events-api');

// Get a reference to the Knowledge Graph Search component
const kgsearch = google.kgsearch('v1');
Expand Down Expand Up @@ -87,11 +88,19 @@ const formatSlackMessage = (query, response) => {
/**
* Verify that the webhook request came from Slack.
*
* @param {object} body The body of the request.
* @param {string} body.token The Slack token to be verified.
* @param {object} req Cloud Function request object.
* @param {string} req.headers Headers Slack SDK uses to authenticate request.
* @param {string} req.rawBody Raw body of webhook request to check signature against.
*/
const verifyWebhook = body => {
if (!body || body.token !== config.SLACK_TOKEN) {
const verifyWebhook = req => {
const signature = {
signingSecret: config.SLACK_SECRET,
requestSignature: req.headers['x-slack-signature'],
requestTimestamp: req.headers['x-slack-request-timestamp'],
body: req.rawBody,
};

if (!verifyRequestSignature(signature)) {
const error = new Error('Invalid credentials');
error.code = 401;
throw error;
Expand Down Expand Up @@ -132,15 +141,12 @@ const makeSearchRequest = query => {
/**
* Receive a Slash Command request from Slack.
*
* Trigger this function by making a POST request with a payload to:
* Trigger this function by creating a Slack slash command with this URL:
* https://[YOUR_REGION].[YOUR_PROJECT_ID].cloudfunctions.net/kgsearch
*
* @example
* curl -X POST "https://us-central1.your-project-id.cloudfunctions.net/kgSearch" --data '{"token":"[YOUR_SLACK_TOKEN]","text":"giraffe"}'
*
* @param {object} req Cloud Function request object.
* @param {object} req.body The request payload.
* @param {string} req.body.token Slack's verification token.
* @param {string} req.rawBody Raw request payload used to validate Slack's message signature.
* @param {string} req.body.text The user's search query.
* @param {object} res Cloud Function response object.
*/
Expand All @@ -153,7 +159,7 @@ exports.kgSearch = async (req, res) => {
}

// Verify that this request came from Slack
verifyWebhook(req.body);
verifyWebhook(req);

// Make the request to the Knowledge Graph Search API
const response = await makeSearchRequest(req.body.text);
Expand Down
1 change: 1 addition & 0 deletions functions/slack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"test": "mocha test/*.test.js --timeout=20000"
},
"dependencies": {
"@slack/events-api": "^2.3.0",
"googleapis": "^46.0.0"
},
"devDependencies": {
Expand Down
7 changes: 6 additions & 1 deletion functions/slack/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,21 @@ const getSample = () => {
const googleapis = {
kgsearch: sinon.stub().returns(kgsearch),
};
const eventsApi = {
verifyRequestSignature: sinon.stub().returns(true),
};

return {
program: proxyquire('../', {
googleapis: {google: googleapis},
'./config.json': config,
'@slack/events-api': eventsApi,
}),
mocks: {
googleapis: googleapis,
kgsearch: kgsearch,
config: config,
eventsApi: eventsApi,
},
};
};
Expand Down Expand Up @@ -115,7 +120,7 @@ describe('functions_slack_search functions_verify_webhook', () => {
const sample = getSample();

mocks.req.method = method;
mocks.req.body.token = 'wrong';
sample.mocks.eventsApi.verifyRequestSignature = sinon.stub().returns(false);

try {
await sample.program.kgSearch(mocks.req, mocks.res);
Expand Down

0 comments on commit b0cbf5a

Please sign in to comment.