CRM Extension : Request Signature


#1

Hello,

I’m trying to follow the authentification process described right here in the Request Signature section :

In there, the specified string to crypt is : App secret + http method + URI + request body (if present)

The code I’ve been trying in the following :

let stringToCrypt = `${config.hubspot.secretKey}${req.method}${req.url}`;
if (Object.keys(req.body).length) {
  stringToCrypt += JSON.stringify(req.body);
}
console.log(stringToCrypt);
// (AppSecret)GET/?userId=(id)&userEmail=(email)&associatedObjectId=(Number)&associatedObjectType=...

const hash = crypto.createHash('sha256').update(stringToCrypt, 'utf8').digest('hex');
console.log('find : ', req.headers['x-hubspot-signature']);
console.log('hash : ', hash);
// those two don't match

The problem I have is that I do not have a example of a string juste before encryption, therefore I cannot
make sure I’m doing the right concatenation before crypting.

Therfore I might be mistaken on the different parts of the string :

  1. AppSecret: Is the AppSecret the Client Secret or are the two of them distinct ?
  2. URl : should it contain the base hostname (http://example.com) should it contain de query parameters ?
  3. Body : How should I apply the body at the end of the string in case of a POST / PUT, is JSON.stringify the correct way add to the string ?

Thank you for your help,

Édouard


#2

Hi @Edouard_DUBOIS,

  1. Yes, the app secret is the same as your app’s client secret
  2. Yes, URI should be the full URI including everything
  3. Depends on the request library you’re using. If req.body is a string, you should append it directly to stringToCrypt. If it’s interpreted by the request library as JSON, then you’ll need to stringify it first. If you’re JSON.stringify()-ing a string, it might end up malformed.

#3

Hello Derek,

Thanks for your help, I’ve got the verification to work for my GET requests (as they don’t have body), your answers for 1 & 2 worked fine, but I’m still not getting the right string to crypt when it comes to POST and PUT requests.

I’ve been trying to simply add a string of the body to my otherwise working string.

This seems to create the correct hash :

secretGEThttp://url.com/hubspot?a=1&b=bar

This does not seem to work the same way :

secretPUThttp://url.com/hubspot{“a”:“1”,“b”:“bar”}

with req.body beeing { a: ‘1’, b: ‘bar’ }

I’m not entirely sure on how I should add the body to the string to crypt.

Do you have an example of the string just before crypting it ?

Thanks for your help,


#4

Hi @Edouard_DUBOIS,

Sounds like you’re using Express? To my knowledge, the Express bodyParser module doesn’t return the raw request body by default (i.e. req.body isn’t the raw string, but parsed JSON). Looks like bodyparser includes a .text() method that returns the body as text instead:


#5

Hi @Derek_Gervais ,

Indeed, I was not adding the raw query but a string of a parsed json.
I did not want to change the content of my req.body so I’ve added a req.rawBodyString on this specific route just for request signature.

const rawBodySaver = (req, res, buf, encoding) => {
  if (buf && buf.length) {
    req.rawBodyString = buf.toString(encoding || 'utf8');
  }
};
app.use('/api/hubspot', express.urlencoded({ verify: rawBodySaver, extended: false }));
app.use(express.urlencoded({ extended: false })); // This is used for other routes

I’m not directly using the bodyParser but the native express methods which are based on bodyParser.

It’s all working perfectly now so thanks a lot for your help on various topics, my CRM Extension is ready to go :+1:

Édouard