In order to validate the hubspot signature, but am currently unable to produce a hash consistent with what I'm seeing in the X-HubSpot-Signature value. I suspect this is because the URL I'm putting into the library is not exactly the correct one, but can't be sure. I.e. I suspect the problem may be similar to having a unexpected trailing slash, badly encoded query parameter or something like that.
I'm using node.js / express, and I'm producing the hash exactly using the method from the code example from the support page. Inputting the example source strings provided does indeed produce the expected checksums.
Is there any way to debug this issue? E.g. being able to see the input source string that HubSpot actually uses to produce the value in X-HubSpot-Signature?
I'm currently only trying to make a GET-request work, so producing the input source string should be straight-forwards. For the sake of it, here's the express code that creates the string.
import crypto from 'crypto';
function validateHubspotSignature(req, res) {
const HubspotSignature = req.get('X-HubSpot-Signature');
const stringToHash =
process.env.HUBSPOT_CLIENT_SECRET
+ req.method
+ req.protocol + '://' + req.get('host') + req.url;
const hash =
crypto.createHash('sha256').update(stringToHash).digest('hex');
// Expecting `hash` and `HubspotSignature` to match, but they do not.
};
I've tried using req.originalUrl etc as well. (I've of course also verified that protocal and method etc are what I expect, and even tried with different combinations, all to no luck).
Incase this is helpful for anyone, I've been trying to inpliment the V2 signature validation using AWS Lambda, unfortunately AWS API Gateway does not expose the original URL and I've been trying to reconstruct it using the queryStringParameters attribute of the event object. Using Postman, I was able to set up a mock server which I pointed the HubSpot API towards. Postman then provided me with an example URL that HubSpot made it's GET request to, I could then use this URL as a template for reconstruction.
Also ran across the the same issue. I wonder if there's any way to solve without hardcoding the specifc order or params as api gateway re-organises them 😞
Incase this is helpful for anyone, I've been trying to inpliment the V2 signature validation using AWS Lambda, unfortunately AWS API Gateway does not expose the original URL and I've been trying to reconstruct it using the queryStringParameters attribute of the event object. Using Postman, I was able to set up a mock server which I pointed the HubSpot API towards. Postman then provided me with an example URL that HubSpot made it's GET request to, I could then use this URL as a template for reconstruction.
I realize this is very late, however I recently encountered this issue and in hopes of saving someone else the time I thought I'd share.
I was trying to validate the CRM Contact Card request which is a GET request. I was stuck for quite a while because I was passing in the exact path it was calling, as per the documentation.
What it turned out to be: "https://mypathhere/api/v1/myfunctionname?userId=???????&userEmail=????????&associatedObjectId=????&associatedObjectType=CONTACT&portalId=??????"
Trouble is, the CRM Contact Card appears to add extra parameters to the query that I wasn't aware of.
I thought they had to be set explicitly but they seem to be sent by default.
yes, you can see these params in your postman mock server in the order hubspot likes them. In serverless functions, you'll need to add portal ID manually to the params since it's apparently not received by the serverless function.
Do you mind sharing with me the request here that you're verifying the signatures for? E.g. Webhook Workflow. This is because the concatention of the X-HubSpot-Signature header is different from the Webhooks API. As documentated here: Verify request signatures in workflow webhooks.
Additionally, could you also share with me the value for stringToHash before the value has been hashed so that I can take a further look into it?
If you're more comfortable, you can share these information across via DM.