Facebook Messenger验证共享位置的X-Hub签名

时间:2017-07-03 20:43:23

标签: facebook security postback sha facebook-messenger

我正在为我的Messenger应用添加X-Hub验证。我在这里了解到了这一点:https://developers.facebook.com/docs/messenger-platform/webhook-reference

我已成功通过简单的短信验证,但是当我发送位置而不是短信时,验证失败,因为我生成的哈希值和Facebook在标题中给出的哈希值不匹配。这是我的验证码:

module.exports.requestIsValid = function(event) {
    if (event['headers']['X-Hub-Signature']) {
        var sha     = event['headers']['X-Hub-Signature']
        var body    = JSON.stringify(event.body);
        return sha == `sha1=${crypto.createHmac('sha1', config.APP_SECRET).update(body).digest('hex')}`;
    }

    return false;   // this return is never called, I know that the first return is the one returning false when it should be true
 }

以下是常规文本消息有效负载的示例:

{ “本体”:{ “对象”: “网页”, “入口”:[{ “ID”: “1366222643461024”, “时间”:1499114399253, “消息接发”:[{ “发件人”:{“ID “:” 1582085681843981 “},” 收件人 “:{” ID “:” 1366222643461024 “},” 时间戳 “:1499114399084,” 消息 “:{” 中 “:” 年年$ cAASAZhi0_wRjO3OtbFdCi5lV2qe4" , “序列”:52192,”文 “:” 测试 “}}]}]},” 方法 “:” POST “ ”principalId“: ”offlineContext_authorizer_principalId“, ”头“:{ ”X-真实-IP“: ”173.252.88.182“,” X -Forwarded-对于 “:” 173.252.88.182" , “主机”: “test.localtunnel.me”, “X - 转发,原”: “https” 开头, “X-Nginx的代理”: “真正的”,“连接“:”close“,”Content-Length“:”270“,”Accept“:” / “,”Accept-Encoding“:”deflate,gzip“,”Content-Type“:”应用/ JSON”, “X-集线器签名”: “SHA1 = 0f51d788fe5f1111846097ad016728cdcd06029f”}, “查询”:{}, “路径”:{}, “同一性”:{ “帐户ID”: “offlineContext_accountId”, “apiKey” : “offlineContext_apiKey”, “主叫方”: “offlineContext_caller”, “cognitoAuthenticationProvider”: “offlineContext_cognitoAuthenticationProvider”, “cognitoAuthenticationType”: “offlineContext_cognitoAuthenticationType”,“搜神记rceIp “:” 127.0.0.1" , “用户”: “offlineContext_user”, “的userAgent”: “”, “userArn”: “offlineContext_userArn”}, “stageVariables”:{}, “IsOffline已”:真}

以下是具有位置的有效负载的示例:

{ “本体”:{ “对象”: “网页”, “入口”:[{ “ID”: “1366222643461024”, “时间”:1499114451619, “消息接发”:[{ “发件人”:{“ID “:” 1582085681843981 “},” 收件人 “:{” ID “:” 1366222643461024 “},” 时间戳 “:1499114451469,” 消息 “:{” 中 “:” 年年$ cAASAZhi0_wRjO3R6DVdCi8v9yqk0" , “序列”:52196,”附件“:[{”title“:”Brandon的位置“,”url“:”https://l.facebook.com/l.php?u=https%3A%2F%2Fwww.bing.com%2Fmaps%2Fdefault.aspx%3Fv%3D2%26pc%3DFACEBK%26mid%3D8100%26where1%3D35.142236316764%252C%2B-106.53531087607%26FORM%3DFBKPL1%26mkt%3Den-US&h=ATOu8uYrLDiFl6wG8RVfhXvwkMl7uB_l2MHqB_uKLhk8qC9p1ua0EOLpGkznVX7Y8YfxSXP7vDuAR7swPmDCw1esH2bwKhNNsZKxVPC2ViC2AFMO_g&s=1&enc=AZMYxff8btvCZWHtzUR4oFL7K2Mg6nXM_O_tRXXL-L8z508UAOauiSRztoRvWdlGCWU1dNRdNK1ls2CGulM8lvzR“,”type“:”location“,”payload“:{”coordinates“:{”lat“:35.142236316764, “长”: - 106.53531087607}}}]}}]}]}, “方法”: “POST”, “principalId”: “offlineContext_authorizer_principalId”, “标题”:{ “X-实-IP”:“173.252.90.239 “ ”X - 转发,对于“: ”173.252.90.239“, ”主机“: ”test.localtunnel.me“, ”X - 转发,原“: ”https“ 开头, ”X-Nginx的代理“:” 真“,”连接“:”关闭“,”内容长度“:”911“,”接受“:” / “,”接受编码“:”deflate,gzip“,”内容 - 类型 “:” 应用/ JSON”, “X-集线器签名”: “SHA1 = 34f23436b2744b9b0cc8776922e7386c454786db”}, “查询”:{}, “路径”:{}, “同一性”:{ “帐户ID”: “offlineContext_accountId” “apiKey”: “offlineContext_apiKey”, “主叫方”: “offlineContext_caller”,“cognitoAuthent icationProvider “:” offlineContext_cognitoAuthenticationProvider “ ”cognitoAuthenticationType“: ”offlineContext_cognitoAuthenticationType“, ”SOURCEIP“: ”127.0.0.1“, ”用户“: ”offlineContext_user“, ”的userAgent“: ”“, ”userArn“: ”offlineContext_userArn“},” stageVariables “:{},” IsOffline已“:真}

如果需要,很高兴提供额外信息。

更新: 经过进一步检查,当有效载荷中存在“attatchments”字段时,验证似乎只会失败。因此,当我发送图片或gif或类似内容时也会失败。

3 个答案:

答案 0 :(得分:1)

您应该将SHA1算法应用于“原始请求主体”。如果你解析身体并将其转换回json;它可能不起作用。

答案 1 :(得分:0)

您的bodyParserJSON应该返回 rawBody

bodyParser.json({
    verify(req, res, buf) {
      req.rawBody = buf;
    },
})

这是我写过的中间件。它使用crypto模块生成sha1

fbWebhookAuth: (req, res, next) => {
    const hmac = crypto.createHmac('sha1', process.env.FB_APP_SECRET);
    hmac.update(req.rawBody, 'utf-8');
    if (req.headers['x-hub-signature'] === `sha1=${hmac.digest('hex')}`) next();
    else res.status(400).send('Invalid signature');
}

最后在您的路线中,您可以将其用作:

app.post('/webhook/facebook', middlewares.fbWebhookAuth, facebook.webhook);

答案 2 :(得分:0)

如果您使用的是 express js

transactor.use { xa =>
    val stream = generateQuery1.stream ++ generateQuery2.stream
    stream.compile.toList.transact(xa)
}.unsafeRunSync

您的中间件

app.use(express.json({
verify:(req, res, buf)=>{
  req.rawBody = buf;
}}))

您的终点

const fbWebhookAuth = (req, res, next) => {
const hmac = crypto.createHmac('sha1', process.env.FB_APP_SECRET);
hmac.update(req.rawBody);
if (req.headers['x-hub-signature'] === `sha1=${hmac.digest('hex')}`) next();
else res.status(400).send('Invalid signature'); }