NodeJS Shopify HMAC验证在webhook实现中失败

yrwegjxp  于 2023-06-22  发布在  Node.js
关注(0)|答案(2)|浏览(193)

我正在开发一个Shopify应用程序。我正在尝试使用Shopify的HMAC身份验证功能验证应用程序上发生的Shopify交易。webhook是通过Shopify Webhook API为主题app_subscribes/update创建的,而shopifyApiSecret是我们Shopify应用程序的客户端密码。这是我们使用的代码片段

async function validateHmac(req: Request) {
  let shopifyApiSecret = config.shopifyAppSecret;

  let hmac: any = req.headers["x-shopify-hmac-sha256"];
  const message = JSON.stringify(req.body);
  const generatedHash = crypto
    .createHmac("sha256", shopifyApiSecret)
    .update(message)
    .digest("base64");
  console.log({ message, generatedHash, hmac });

  const signatureOk = crypto.timingSafeEqual(
    Buffer.from(generatedHash),
    Buffer.from(hmac)
  );
  if (signatureOk) {
    return true;
  } else {
    return false;
  }
}

我们尝试比较了两种方法,即使用===和使用timingSafeEqual,但函数总是返回false,并且generatedHash和hmac在检查时不相等。有谁能告诉我这个实现有什么问题吗?先谢谢你了。

rekjcdws

rekjcdws1#

下面是我们在. Net中完成的实现。你可以从下面的代码中理解逻辑:

string hmacHeader = Convert.ToString(Request.Headers["X-Shopify-Hmac-SHA256"]);
string requestJson = JsonSerializer.Serialize(request);

HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(APISecretKey));
string hash = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(requestJson)));

isSuccess = string.Equals(hmacHeader, hash, StringComparison.OrdinalIgnoreCase);
qlvxas9a

qlvxas9a2#

问题出在我们生成消息所消耗的数据上。我们能够解决它通过使用我们的路由器中的express功能

express.json({
  limit: '10mb',
  verify: (req, _res, buf) => {
    (req as any).rawBody = buf;
  },
});

并将rawBody传递给update函数。

async function validateHmac(req: Request) {
  let shopifyApiSecret = config.shopifyAppSecret;

  let hmac: any = req.headers["x-shopify-hmac-sha256"];
  const message = req.rawBody;
  const generatedHash = crypto
    .createHmac("sha256", shopifyApiSecret)
    .update(message)
    .digest("base64");
  console.log({ message, generatedHash, hmac });

  const signatureOk = crypto.timingSafeEqual(
    Buffer.from(generatedHash),
    Buffer.from(hmac)
  );
  if (signatureOk) {
    return true;
  } else {
    return false;
  }
}

相关问题