Charca / bootbot

Facebook Messenger Bot Framework for Node.js
MIT License
970 stars 252 forks source link

Error: Couldn't validate the request signature #174

Open balazsorban44 opened 5 years ago

balazsorban44 commented 5 years ago

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:

https://github.com/Charca/bootbot/blob/8884e72403ced1bcf5615645251968640b7c3936/lib/BootBot.js#L681-L698

On another repo, some people claim they solved the problem: https://github.com/botmasterai/botmaster-messenger/issues/15#issuecomment-414714190

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 https://github.com/Charca/bootbot/blob/8884e72403ced1bcf5615645251968640b7c3936/lib/BootBot.js#L36

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 commented 5 years ago

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 commented 4 years ago

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());