4

The Uber documentation say

The value of this field is a hexadecimal HMAC signature of the webhook HTTP request body, using the client secret as a key and SHA256 as the hash function.

But what is the HTTP request body? I assume it is the JSON body received from the webhook (https://developer.uber.com/docs/webhooks#section-example-post).

If it is, then how to validate it in NodeJS as the crypto module for HMAC doesn't accept JSON[I've tried to stringify the JSON, but it generates a different hash]. Or how to I convert the JSON into a buffer, since that is the next best option

If not, then what should I be using?

[UPDATE1] Code used for the task:

app.post("/",function(req,res){
const crypto = require('crypto');
var input = res.body
var str_input=JSON.stringify(input)

const hmac = crypto.createHmac('sha256', '<CLIENT SECRET>');

hmac.update(str_input);
console.log(hmac.digest('hex')); // print same as below
console.log("e034ac7db29c3c0c10dfeced41a6cd850ed74c1c3c620863d47654cc7390359a")
})
alt-ctrl-dev
  • 689
  • 1
  • 6
  • 21
  • 1
    you are correct that `JSON.stringify(req.body)` is what you should be passing to your hashing function. Can you include the code for your hashing function in the question? – Andrew Noonan Mar 23 '16 at 05:27
  • @AndrewNoonan I've added the code for the same – alt-ctrl-dev Mar 23 '16 at 09:06
  • Please, can you post the final code? I added the answer's replace to my code as: `var input = JSON.stringify(req.body).replace(/\//g, '\\' + '/');` but this didn't work. Uber signature keeps not being equal to the header one. – gaskbr Aug 31 '17 at 16:55

2 Answers2

4

Updated Answer

Uber considered the insertion of backslashes into webhook bodies a bug and released a fix. The workaround below will now break comparisons. As of 4/28/2016, clients written in Node should just perform the comparison without modifying the webhook body. Clients in languages that don't share Node's behavior of ignoring blackslashes in escape sequences are unaffected.

Original Answer

JS ignores the backslash when reading escape sequences in a string. The missing backslash is breaking your comparison because it's included in webhook event signatures.

An immediate workaround is to re-insert those backslashes using a regex.

var reconstitutedWebhookBody = input.replace(/\//g, '\\' + '/');

That regex will need to be extended if webhooks ever start including other escapable characters.

Community
  • 1
  • 1
7imon7ays
  • 191
  • 3
  • First time I've come across this problem in JS. Thank you for the reply! – alt-ctrl-dev Mar 24 '16 at 04:38
  • Please, can you post the final code? I added the answer's replace to my code as: `var input = JSON.stringify(req.body).replace(/\//g, '\\' + '/');` but this didn't work. Uber signature keeps not being equal to the header one. – gaskbr Aug 31 '17 at 16:56
0

I had the same problem. Uber send json with spaces before keys and values. Like this

{"event_id": "...", "resource_href": "...", "meta": {"status": "...", "rider_id": "...", "user_id": "...", "resource_id": "..."}, "event_type": "...", "event_time": ...}

You can do this before activating boryparser. And create hex from this data

app.use(function (req, res, next) {

let data = "";
req.on('data', function(chunk){data += chunk});
req.on('end', function(){
    req.jsonBody = JSON.parse(data);
    req.rawBody = data;
    req.originalUberReq = data;
});
next();
});