Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error: Couldn't validate the request signature #174

Open
balazsorban44 opened this issue Apr 10, 2019 · 2 comments
Open

Error: Couldn't validate the request signature #174

balazsorban44 opened this issue Apr 10, 2019 · 2 comments

Comments

@balazsorban44
Copy link

balazsorban44 commented Apr 10, 2019

It is not the first issue related to this problem (see #14 #40 #48 #66 #67 #69 #84 #110), but as I see that most of them ended up being closed without a solution, I was thinking of opening it again, with some extra thoughts. So I searched the Internet, and the most possible source of the problem is here:

bootbot/lib/BootBot.js

Lines 681 to 698 in 8884e72

_verifyRequestSignature(req, res, buf) {
var signature = req.headers['x-hub-signature'];
if (!signature) {
throw new Error('Couldn\'t validate the request signature.');
} else {
var elements = signature.split('=');
var method = elements[0];
var signatureHash = elements[1];
var expectedHash = crypto.createHmac('sha1', this.appSecret)
.update(buf)
.digest('hex');
if (signatureHash != expectedHash) {
throw new Error('Couldn\'t validate the request signature.');
}
}
}
}

On another repo, some people claim they solved the problem:
botmasterai/botmaster-messenger#15 (comment)

I am just curious if the following has been considered when the _verifyRequestSignature function was created?:

Please note that the calculation is made on the raw escaped unicode version of the payload, with lower case hex digits. For example, the string äöå will be escaped to \u00e4\u00f6\u00e5. The calculation also escapes / to /, < to \u003C, % to \u0025 and @ to \u0040. If you just calculate against the decoded bytes, you will end up with a different signature.
Source: https://developers.facebook.com/docs/messenger-platform/webhook/#security

If not, maybe this might be helpful?:

String.prototype.toUnicode = function(){
    var result = ""
    for(var i = 0; i < this.length; i++){
        // Assumption: all characters are < 0xffff
        result += "\\u" + ("000" + this[i].charCodeAt(0).toString(16)).substr(-4)
    }
    return result
}

UPDATE: Playing with it on a fork locally, I found out, that the Error that gets triggered is on line 684 in BootBot.js, cause signature is undefined. Now I am not an expert on this topic, so maybe is it me, who should send an X-Hub-Signature? I am testing with curl:

curl -X POST \
  http://localhost:5000/webhook \
  -H 'Content-Type: application/json' \
  -H 'cache-control: no-cache,no-cache' \
  -d '{"object": "page", "entry": [{"messaging": [{"message": "TEST_MESSAGE"}]}]}'

image

Clearly, there is no x-hub header, not even in Facebook's example!

What I tried is to change the code on line 36

this.app.use(this.webhook, bodyParser.json({ verify: this._verifyRequestSignature.bind(this) }));

to this (using x-hub-signature from npm):

    this.app.use(this.webhook, bodyParser.json({ verify: webhookMiddleware.extractRawBody }));
    this.app.use(webhookMiddleware({
      algorithm: 'sha1',
      secret: 'secret',
      require: true
    }));

By doing that, I now actually get a different error:

BadRequestError: Missing X-Hub-Signature header

Which at least describes the problem a bit better. So at the end of the day, I still have the same problem, so if you can and could help me to explain what X-Hub-Signature's value should be, I would appreciate it!

Without this, I don't know how to develop/test locally, and I have to deploy every time I make a small change to test.

@Charca ?

@Charca
Copy link
Owner

Charca commented Apr 15, 2019

Hey @balazsorban44, I've actually never encountered this error myself, but since this error is thrown when your bot tries to verify that the request comes from Facebook, you can probably bypass the verification locally while you test it.

It's been a while since I've worked with this project, but one thing I can suggest is changing line 36 in BootBot.js from:

this.app.use(this.webhook, bodyParser.json({ verify: this._verifyRequestSignature.bind(this) }));

to:

this.app.use(this.webhook, bodyParser.json());

If that works, then we can probably make it an option in the bot's config object so that you can specify that you want to skip the signature verification when running it locally.

Let me know how that goes!

@pinchez254
Copy link

This is because your JSON is not being propery parsed. Body parser worked for me perfectly . example const bodyParser = require("body-parser"), app = express().use(bodyParser.json());

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants