We use cookies to make HubSpot's community a better place. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. To learn more, and to see a full list of cookies we use, check out our Cookie Policy (baked goods not included).
Nov 30, 2022 9:49 AM - edited Nov 30, 2022 9:49 AM
For other cases it validates ok (ex. CRM card) but I can't validate it when the request has body on it. I've used https://webhook.site to check request structure and data from our Sentry platform in order to reproduce the issue and try to get the correct hash (I'm using the python hubspot client 7.0.0 to validate the request).
So, how would the following payload look as a string for the calculation:
{
"origin": {
"portalId": 22676670,
"actionDefinitionId": 27766097,
"actionDefinitionVersion": 1,
"extensionDefinitionId": 27766097,
"extensionDefinitionVersionId": 1,
},
"inputFieldName": "selectTemplate",
"fetchOptions": {},
"fields": {
"messageType": {
"fieldKey": "messageType",
"fieldValue": {
"valueType": "STATIC",
"value": "template",
"effectiveValueType": "SINGLE",
},
},
"language": {
"fieldKey": "language",
"fieldValue": {
"valueType": "STATIC",
"value": "af",
"effectiveValueType": "SINGLE",
},
},
},
"portalId": 22676670,
"extensionDefinitionId": 27766097,
"extensionsDefinitionVersion": 1,
"inputFields": {
"messageType": {"type": "STATIC_VALUE", "value": "template"},
"language": {"type": "STATIC_VALUE", "value": "af"},
},
"webhookUrl": "https://account-api.get.chat/proxy/packages/asdf1234?path=/api/v1/plugins/public/webhook/&format=json&type=hubspot&webhook_type=templates",
}
Thanks in advance,
Sergi
Dec 1, 2022 2:31 AM
Hi.
If you mean like below, your should stringify request body.
>sha256(Client secret + http method + URI + request body)
stringified example request body
{"origin":{"portalId":22676670,"actionDefinitionId":27766097,"actionDefinitionVersion":1,"extensionDefinitionId":27766097,"extensionDefinitionVersionId":1},"inputFieldName":"selectTemplate","fetchOptions":{},"fields":{"messageType":{"fieldKey":"messageType","fieldValue":{"valueType":"STATIC","value":"template","effectiveValueType":"SINGLE"}},"language":{"fieldKey":"language","fieldValue":{"valueType":"STATIC","value":"af","effectiveValueType":"SINGLE"}}},"portalId":22676670,"extensionDefinitionId":27766097,"extensionsDefinitionVersion":1,"inputFields":{"messageType":{"type":"STATIC_VALUE","value":"template"},"language":{"type":"STATIC_VALUE","value":"af"}},"webhookUrl":"https://account-api.get.chat/proxy/packages/asdf1234?path=/api/v1/plugins/public/webhook/&format=json&type=hubspot&webhook_type=templates"}
Thanks.
Dec 1, 2022 5:12 AM
Hi, thank you for your reply. Unfortunately, even using the stringified request body you provided, I'm still unable to get the correct signature... Client secret, method and URI should be fine since requests without body validate well. Is your example simply my json without spaces or new lines or is that actually what the part of the request body looks like in the source string right before your systems generate the signature?
We are using PRE_FETCH_OPTIONS in our action to add a query parameter to the webhook url among other things, this is how it looks:
exports.main = (event, callback) => { callback({ webhookUrl: event.webhookUrl + \"&portalId=\" + event.origin.portalId, body: JSON.stringify(event), accept: 'application/json' });}
Could this be "altering" the information at the moment of generating the signature on your side?
Thanks and regards,
Sergi
Dec 1, 2022 7:10 PM
In my case, it works.
I've only verified with URLs like 'https://example.com/webhook/XXXXX'.
import crypto from 'crypto';
import { Request } from 'express';
...
// request: Request
const signature = request.get('x-hubspot-signature');
const full = `${request.protocol}://${request.get('host')}${request.originalUrl}`;
const body = JSON.stringify(request.body);
// v2 signature
const contents = appSecret + method + uri + body;
const hash = crypto.createHash('sha256').update(contents).digest('hex');
// check
const isValid = hash == signature;
...
If it works without a body,
I don't think "PRE_FETCH_OPTIONS" is relevant.