node.js - 如何验证来自 Slack Events API 的请求

标签 node.js express http-post slack-api

我正在使用 validate-slack-request用于验证我传入的 slack 请求的包来自 slack。这适用于 Slash 命令和交互式组件(按钮等)。但是它不适用于 Events API
我注意到 POST 请求正文对于 Events API 具有不同的格式。没有 payload .但我不清楚什么 slack 给我用来验证。代码如下

//This WORKS
app.post("/interactiveCommand", async (req, res) => {
  const legit = validateSlackRequest(process.env.SLACK_SIGNING_SECRET, req, false);
  if (!legit) {
    console.log("UNAUTHORIZED ACCESS ", req.headers, req.body);
    return res.status(403).send("Unauthorized");
  }
  await interactiveCommand(...);
  return;
});

//This does NOT WORK
app.post("/slackEvents", parser, json, async (req, res) => {
  const legit = validateSlackRequest(process.env.SLACK_SIGNING_SECRET, req, false);
  if (!legit) {
    console.log("UNAUTHORIZED ACCESS ", req.headers, req.body);
    res.status(403).send("Unauthorized");
  } else {
    try {
      switch (req.body.event.type) {
        case "message":
          await handleMessageEvent(...);
          break;
        case "app_home_opened":
          res.status(200).send();
          await updateUserHomePage(...);
          break;
        default:
          res.status(200).send();
          return;
      }
    } catch(e) {
      console.log("Error with event handling! ", e);
    }
  }
});

const crypto = require('crypto')
const querystring = require('querystring')

// Adhering to RFC 3986
// Inspired from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
function fixedEncodeURIComponent (str) {
  return str.replace(/[!'()*~]/g, function (c) {
    return '%' + c.charCodeAt(0).toString(16).toUpperCase()
  })
}

/**
 * Validate incoming Slack request
 *
 * @param {string} slackAppSigningSecret - Slack application signing secret
 * @param {object} httpReq - Express request object
 * @param {boolean} [logging=false] - Enable logging to console
 *
 * @returns {boolean} Result of vlaidation
 */
function validateSlackRequest (slackAppSigningSecret, httpReq, logging) {
  logging = logging || false
  if (typeof logging !== 'boolean') {
    throw new Error('Invalid type for logging. Provided ' + typeof logging + ', expected boolean')
  }
  if (!slackAppSigningSecret || typeof slackAppSigningSecret !== 'string' || slackAppSigningSecret === '') {
    throw new Error('Invalid slack app signing secret')
  }
  const xSlackRequestTimeStamp = httpReq.get('X-Slack-Request-Timestamp')
  const SlackSignature = httpReq.get('X-Slack-Signature')
  const bodyPayload = fixedEncodeURIComponent(querystring.stringify(httpReq.body).replace(/%20/g, '+')) // Fix for #1
  if (!(xSlackRequestTimeStamp && SlackSignature && bodyPayload)) {
    if (logging) { console.log('Missing part in Slack\'s request') }
    return false
  }
  const baseString = 'v0:' + xSlackRequestTimeStamp + ':' + bodyPayload
  const hash = 'v0=' + crypto.createHmac('sha256', slackAppSigningSecret)
    .update(baseString)
    .digest('hex')

  if (logging) {
    console.log('Slack verifcation:\n Request body: ' + bodyPayload + '\n Calculated Hash: ' + hash + '\n Slack-Signature: ' + SlackSignature)
  }
  return (SlackSignature === hash)
}

最佳答案

我用这个将文本有效负载转换为 json:

IFS=$'\n'
if [ "$REQUEST_METHOD" = "POST" ]; then
 if [ "$CONTENT_LENGTH" -gt 0 ]; then
  cat - > /tmp/file.txt
 fi
fi
cat /tmp/file.txt | sed -e "s/^payload=//g" | perl -pe 's/\%(\w\w)/chr hex $1/ge' > /tmp/file.json

关于node.js - 如何验证来自 Slack Events API 的请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64794287/

相关文章:

node.js - Keystone js 音频视频支持以及与 rethinkdb 的连接?

javascript - Express - 获取正在运行的域名服务器

php - 如何在 codeigniter 中检查请求是 POST 还是 GET 请求?

powershell - 如何使用 Powershell httpListener 捕获 post/get 变量?

javascript - express 中的请求正文未定义?

delphi - 从 120 更新到 Indy 130 软件包,现在此代码不起作用

javascript - 如何将多个集合数据从mongodb渲染到node js中的页面

node.js - nodejs - 连续 execSync 函数出现意外行为

javascript - 如何覆盖 Google Cloud Tasks Node.js 客户端的重试配置

javascript - 在 Mocha 测试中没有调用函数