Xero Webhook 验证在 NodeJS/Express 后端失败

问题描述 投票:0回答:1

我正在尝试在 NodeJS 和 Express 环境中为演示 Xero 帐户设置一个 Webhook。看来 Xero 提供的 Webhooks 密钥与接收他们发送到我的服务器的测试的意图不匹配。

我遵循了 Xero 团队三年前在他们的 Medium 文章 上提供的指南。这是从 Xero-Node Hooks 部分检索的 我已经复制了代码而不使用类来获得此结果:

import * as crypto from "crypto";
import express from "express";
import { Request, Response } from "express";

const app = express();

app.use("/webhooks", express.raw({ type: "application/json" }));
app.use(express.json());

function verifyWebhookEventSignature(req: Request) {
  const computedSignature = crypto
    .createHmac(
      "sha256",
      process.env.XERO_WEBHOOK_KEY
    )
    .update(req.body.toString())
    .digest("base64");
  const xeroSignature = req.headers["x-xero-signature"];

  if (xeroSignature === computedSignature) {
    console.log("Signature passed! This is from Xero!");
    return true;
  } else {
    console.log(
      "Signature failed. Webhook might not be from Xero or you have misconfigured something..."
    );
    console.log(
      `Got {${computedSignature}} when we were expecting {${xeroSignature}}`
    );
    return false;
  }
}

app.post("/webhooks", async (req: Request, res: Response) => {
  console.log(
    "webhook event received!",
    req.headers,
    req.body,
    JSON.parse(req.body)
  );
  return verifyWebhookEventSignature(req)
    ? res.status(200).send()
    : res.status(401).send();
});

app.listen(5000, () => {
  console.log(`Server is running on port ${5000}`);
});

在上面的示例中,单击 Xero Webhook 页面上的“意图接收”按钮后即可到达端点。但我从来没有成功过R

esponse to incorrectly signed payload not 401. Last sent at 2023-11-27 18:00:53 UTC
。有几次我收到“签名已通过!这是来自 Xero!”的消息。但结果似乎仍然是一样的,最终结果不是 Xero 所期望的,并再次用
Response to incorrectly signed payload not 401. Last sent at 2023-11-27 18:00:53 UTC
吐出上述错误。

ngrok 报道: POST /webhooks 401 未经授权 POST /webhooks 401 未经授权

我还在 Xero 的同一博客部分上再次尝试了他们的旧指南,但不幸的是得到了相同的结果。

深入研究后,签名和计算签名似乎相对相似,但并不完全相同。以下是失败示例之一的响应(Webhook 密钥在发布后已更改): {4i4UlslXwPfrYZNMoV1IIL52UdW8M3QEZMadUgvJ2Yc=} 当我们期待 {4i4UlslXwPfrYZNMo/1IIL52UdW8M3QEZMadUgvJ2Yc=}

表格帖子提到了 n8n 上的斜线问题,他们的建议是替换斜线。我尝试了全局字符串替换和单个字符串替换。这确实删除了斜杠,但如上面的示例所示,实际字符似乎不同,其中斜杠来自计算签名和 xero 签名。

我还尝试通过从 Xero 中删除 webhook 并使用 Ngrok URL 重新创建几次来重新生成密钥,但得到了相同的结果。

这是我收到的一个例子,签名通过和签名失败,但仍然收到来自 xero 的 ICR:

Server is running on port 5000
webhook event received! {
  host: 'eeb6-81-106-82-109.ngrok.io',
  'content-length': '95',
  'content-type': 'application/json; charset=utf-8',
  'x-forwarded-for': '52.20.64.83',
  'x-forwarded-host': 'eeb6-81-106-82-109.ngrok.io',
  'x-forwarded-proto': 'https',
  'x-xero-signature': 'kQtanVOgzl9tEdBTrgDDAv9Thr+ThIGdDDDVFU5L/ZU=',
  'accept-encoding': 'gzip'
} <Buffer 7b 22 65 76 65 6e 74 73 22 3a 5b 5d 2c 22 66 69 72 73 74 45 76 65 6e 74 53 65 71 75 65 6e 63 65 22 3a 20 30 2c 22 6c 61 73 74 45 76 65 6e 74 53 65 71 ... 45 more bytes> {
  events: [],
  firstEventSequence: 0,
  lastEventSequence: 0,
  entropy: 'EDEKUDLFUPIMATQBJWMR'
}
Signature passed! This is from Xero!
webhook event received! {
  host: 'eeb6-81-106-82-109.ngrok.io',
  'content-length': '95',
  'content-type': 'application/json; charset=utf-8',
  'x-forwarded-for': '52.20.64.83',
  'x-forwarded-host': 'eeb6-81-106-82-109.ngrok.io',
  'x-forwarded-proto': 'https',
  'x-xero-signature': 'kQtanVOgzl9tEdBTrgDDAv9Thr+ThIGdDDDV/U5L/ZU=',
  'accept-encoding': 'gzip'
} <Buffer 7b 22 65 76 65 6e 74 73 22 3a 5b 5d 2c 22 66 69 72 73 74 45 76 65 6e 74 53 65 71 75 65 6e 63 65 22 3a 20 30 2c 22 6c 61 73 74 45 76 65 6e 74 53 65 71 ... 45 more bytes> {
  events: [],
  firstEventSequence: 0,
  lastEventSequence: 0,
  entropy: 'EDEKUDLFUPIMATQBJWMR'
}
Signature failed. Webhook might not be from Xero or you have misconfigured something...
Got {kQtanVOgzl9tEdBTrgDDAv9Thr+ThIGdDDDVFU5L/ZU=} when we were expecting {kQtanVOgzl9tEdBTrgDDAv9Thr+ThIGdDDDV/U5L/ZU=}

Image of Xero Webhook page

任何帮助/建议将不胜感激。非常感谢

node.js webhooks ngrok xero-api
1个回答
0
投票

更新:

经过几个小时的进一步测试,这个问题对我来说似乎是 ngrok。作为参考,我运行的 ngrok 命令只是

ngrok http 5000
。在 Windows (22H2) 上启用/禁用防火墙的设置和测试过程中没有显示任何错误,仍然返回相同的结果。

不幸的是,我很难找到 ngrok 的替代品,并从 github 上的这个列表中尝试了其他多个人 https://github.com/anderspitman/awesome-tunneling 但最终对我来说第一次尝试的是 Loophole通过执行

loophole http 5000
(似乎需要一个帐户才能设置)。

与ngrok enter image description here

有漏洞 enter image description here

Xero 提到,要使 Webhook 成功,必须满足某些标准。 我的假设是,各种隧道解决方案处理 Webhook 请求的方式可能存在一些细微的差异,这会在验证 ICR 时引起问题。

编辑

这个问题不是 ngrok 的问题,而是通常由于请求有效负载被无意修改而导致。尝试对此端点使用 bodyparser.raw({type:'application/json'}) 或express.raw({type:'application/json'}) 。并确保禁用任何其他主体修改中间件。

© www.soinside.com 2019 - 2024. All rights reserved.