偶尔 Hubspot Webhook 签名不匹配

huangapple go评论98阅读模式
英文:

Occassional Hubspot webhook signature mismatch

问题

我有一个服务,它监听 Hubspot webhook 请求(POST 请求),并使用 Hubspot 的 v3 签名对每个请求进行身份验证。以下是代码(typescript):

const requestSignature = params?.headers?.['x-hubspot-signature-v3']
const requestTimestamp = params?.headers?.['x-hubspot-request-timestamp']

// 验证时间戳
const MAX_ALLOWED_TIMESTAMP = 300000 // 5 分钟的毫秒数
const currentTime = Date.now()
if (currentTime - requestTimestamp > MAX_ALLOWED_TIMESTAMP) {
  throw new GeneralError('Hubspot signature v3 时间戳无效')
}

// 计算签名
const clientSecret = <...snip: 从秘密存储获取秘钥...>
const body = JSON.stringify(params.body)
const source = params.method + params.uri + body + requestTimestamp
const signature = crypto.createHmac('sha256', clientSecret).update(source).digest('base64')

// 验证签名
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(requestSignature))) {
  throw new NotAuthenticated('Hubspot signature v3 不匹配')
}

这个代码大多数情况下都能正常工作,但偶尔签名不匹配。这不是因为缺少数据或我们方面的错误数据,我已经验证了正确的头存在等。也不是调用 crypto.timingSafeEqual 的问题,我已经验证了两个签名不匹配。

有其他人遇到过类似情况吗?是什么原因导致 Hubspot 的某些请求无法通过签名验证?

英文:

I have a service which listens to Hubspot webhook requests (POSTs), and authenticates each request using Hubspot's v3 signature. The code is this (typescript):

const requestSignature = params?.headers?.[&#39;x-hubspot-signature-v3&#39;]
const requestTimestamp = params?.headers?.[&#39;x-hubspot-request-timestamp&#39;]

// Validate timestamp
const MAX_ALLOWED_TIMESTAMP = 300000 // 5 minutes in milliseconds
const currentTime = Date.now()
if (currentTime - requestTimestamp &gt; MAX_ALLOWED_TIMESTAMP) {
  throw new GeneralError(&#39;Hubspot signature v3 timestamp is invalid&#39;)
}

// Calculate signature
const clientSecret = &lt;...snip: get secret from secrets store...&gt;
const body = JSON.stringify(params.body)
const source = params.method + params.uri + body + requestTimestamp
const signature = crypto.createHmac(&#39;sha256&#39;, clientSecret).update(source).digest(&#39;base64&#39;)

// Validate signature
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(requestSignature))) {
  throw new NotAuthenticated(&#39;Hubspot signature v3 mismatch&#39;)
}

This works most of the time, but occasionally the signatures don't match. It's not because of any missing data, or incorrect data on our side -- I have verified that the correct headers exist, etc. And it's not the call to crypto.timingSafeEqual -- I have verified that the two signatures do not match.

Has anyone else experienced this before? What could cause just some of the requests from Hubspot to fail signature validation?

答案1

得分: 0

@CBroe 在上面的评论中提供了答案的暗示,但问题实际上出现在 JSON.stringify() 之前:我们的应用程序使用全局钩子,在某些情况下会转换请求有效载荷。在这种情况下,有效载荷 JSON 中的一个字符串值带有尾随空格,并且我们的某个钩子修剪所有输入数据。使用原始未经处理的请求有效载荷执行上面的签名验证器解决了问题。

英文:

@CBroe, in his comment above, provided a hint to the answer, but the problem actually came before JSON.stringify(): Our app uses global hooks which transforms the request payload in some cases. In this case, one of the string values in the payload JSON had a trailing space, and one of our hooks trims all input data. Executing the above signature validator with the original un-processed request payload solved the problem.

huangapple
  • 本文由 发表于 2023年6月19日 21:17:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76507027.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定