Unable to validate Twilio request in Google cloud function

主宰稳场 提交于 2021-02-07 04:29:15

问题


I have a Google cloud function to which Twilio sends POST requests with SMS statuses but I am unable to verify that the requests are coming from Twilio using any of the methods outlined in https://www.twilio.com/docs/usage/security

My first attempt consisted of using the validateRequest function, as shown in the code below

const twilio = require('twilio');

let url = 'https://....cloudfunctions.net/...'
let token = 'XXXX';
let header = request.headers['x-twilio-signature'];
let sortedKeys = Object.keys(request.body).sort();
let sortedParams = {};

sortedKeys.forEach(key => {
  sortedParams[key] = request.body[key];
});

let validated = twilio.validateRequest(token, header, url, sortedParams);

I confirmed that the value of token matched the auth token from the Twilio account settings, sortedParams contained alphabetically sorted camel-cased Twilio request params and the url matched that which was passed to the Twilio client when creating the SMS. However, validateRequest would always return false.

My next attempt involved hashing the combination of the url and request params by copying the code from https://www.twilio.com/docs/libraries/reference/twilio-node/3.18.0/webhooks_webhooks.js.html

const crypto = require('crypto')

sortedKeys.forEach(key => {
  url = `${url}${key}${request.body[key]}`;
});

let signature = crypto
    .createHmac('sha1', token)
    .update(Buffer.from(url, 'utf-8'))
    .digest('base64');

Upon comparing the value of signature to that of the header, the two never matched.


回答1:


Twilio developer evangelist here.

I recommend using the validateRequest method as that does most of the work for you.

You don't need to perform the parameter sorting that you've attempted, JavaScript objects are unordered and the library sorts and appends the parameters to the URL string already.

Things you need to check are that the URL is the exact webhook URL you set in your Twilio console, including the entire path and any query parameters that are included.

Also, have you ensured that request.body is populated and that your express app is using body-parser to parse the incoming request as url encoded form parameters?

app.use(bodyParser.urlencoded({ extended: false }));

If you are trying to validate the request as middleware, make sure that the request validation is done after body parsing.

Does any of that help at all?




回答2:


It turns out that the there was nothing wrong with the validateRequest but rather the way I was declaring the token. Instead of hard-coding it in the function's code, it was being retrieved from a Google storage bucket as a buffer and then converted to a string. For unknown reasons, even though visually, the retrieved value matched the original token, a === comparison returned false. Once I hard-coded the token, everything worked.



来源:https://stackoverflow.com/questions/51372600/unable-to-validate-twilio-request-in-google-cloud-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!