botmasterai / botmaster-messenger

The Facebook Messenger Botmaster integration
MIT License
15 stars 9 forks source link

verifyRequestSignature breaks with special characters! #15

Closed lucaslo closed 6 years ago

lucaslo commented 6 years ago

Hi! I have a bot that works perfectly except when I use a special character (like í ç ó ).

0|botPerfe |     at IncomingMessage.emit (events.js:207:7)
0|botPerfe |     at endReadableNT (_stream_readable.js:1059:12)
0|botPerfe |     at _combinedTickCallback (internal/process/next_tick.js:138:11)
0|botPerfe |     at process._tickDomainCallback (internal/process/next_tick.js:218:9)
0|botPerfe | Error: wrong signature
0|botPerfe |     at MessengerBot.__verifyRequestSignature (/home/lucaslo/programas/mensageiro/bots/botperfeito/node_modules/botmaster-messenger/lib/messenger_bot.js:176:13)
0|botPerfe |     at /home/lucaslo/programas/mensageiro/bots/botperfeito/node_modules/body-parser/lib/read.js:104:9
0|botPerfe |     at invokeCallback (/home/lucaslo/programas/mensageiro/bots/botperfeito/node_modules/raw-body/index.js:224:16)
0|botPerfe |     at done (/home/lucaslo/programas/mensageiro/bots/botperfeito/node_modules/raw-body/index.js:213:7)
0|botPerfe |     at IncomingMessage.onEnd (/home/lucaslo/programas/mensageiro/bots/botperfeito/node_modules/raw-body/index.js:273:7)
0|botPerfe |     at emitNone (events.js:105:13)
0|botPerfe |     at IncomingMessage.emit (events.js:207:7)
0|botPerfe |     at endReadableNT (_stream_readable.js:1059:12)
0|botPerfe |     at _combinedTickCallback (internal/process/next_tick.js:138:11)
0|botPerfe |     at process._tickDomainCallback (internal/process/next_tick.js:218:9)

I've nailed it down to this piece of code.

  __verifyRequestSignature(req, res, buf) {
    const signature = req.headers['x-hub-signature'];
    console.log("SIGNATURE")
    console.log(signature)
    const signatureHash = signature ? signature.split('=')[1] : undefined;
    const expectedHash = crypto.createHmac('sha1', this.credentials.fbAppSecret)
                        .update(buf)
                        .digest('hex');
    if (signatureHash !== expectedHash) {
      throw new Error('wrong signature');
    }
  }

I do have a code to remove those charactes, but the error is thrown before any middleware (or me having access to the text). Can anybody offer me a solution to this problem? Is there a workarround?

jdwuarin commented 6 years ago

Hi,

That is quite a weird bug indeed. could potentially be a bug with crypto itself or with the signature sent back from facebook directly.

Either way, it's clearly weird. I wonder if either of them strips the characters out then encrypts. That could be something to try out.

If a solution is really hard to find, I wouldn't advise to just bypass the code as it makes the bot safer.

I'll try and have a play with it over the weekend and see what it could be.

marcel0ll commented 6 years ago

Any updates on this issue?

marcel0ll commented 6 years ago

Hey @jdwuarin Me and @lucaslo got around the problem by using a map of replacements.

const characterMapping = {
  "á": "\\u00e1",
  "à": "\\u00e0",
...
}

__verifyRequestSignature(req, res, buf) {
  ...
  let bufString = buf.toString('utf8')
  for(let char in characterMapping) {
    bufString = bufString.replace(char, characterMapping[char])
  }
  const expectedHash = crypto.createHmac('sha1', this.credentials.fbAppSecret)
                      .update(bufString)
                      .digest('hex');
  ...
}

I basically followed the description on facebook about escaping some characters to unicode.

Do you think there is a better solution for this?

jdwuarin commented 6 years ago

Hey @0tho, This looks like the proper solution. Thanks for that! If you create a pull request for it, I'll create a new release for it.

marcel0ll commented 6 years ago

Ok, I will as soon as possible.

balazsorban44 commented 5 years ago

@lucaslo @0tho @jdwuarin Has this eventually been fixed? I am searching around the Internet, and I see that many facebook bots have a similar problem.

marcel0ll commented 5 years ago

Hey @balazsorban44, it has been some time so I don't remember all the details, but if I remember correctly we had an nginx route acting as a proxy that was messing with the encoding (or something like that). Using the code from my now closed PR helped for a while, but it was just a hack. I would recommend looking into your stack and finding what is messing with your encoding.