Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shopify webhook - Failed sha256 verification #769

Closed
jaaneh opened this issue Dec 2, 2023 Discussed in #768 · 4 comments
Closed

Shopify webhook - Failed sha256 verification #769

jaaneh opened this issue Dec 2, 2023 Discussed in #768 · 4 comments

Comments

@jaaneh
Copy link
Contributor

jaaneh commented Dec 2, 2023

I opened this originally in discussions, but unsure if this is better suited as an issue so re-opening it here. Feel free to close one and continue conversation in the other. Discussion #768


Hey there,

I've been trying to get up an going with the Shopify integration, however every time I trigger an event through Shopify it leads to a "Failed sha256 verification" error.

image

The webhook succeeds obviously when using the test event in Trigger, and it returns the payload (using the example below). I have set up webhook in Shopify, and I am also using the correct secrets/env vars.

I am self-hosting Trigger, and have input the DEV URL to Shopify as the app is not hosted yet.

Seeing as Shopify doesn't have a way to insert the secret that Trigger gives you, and they instead give us one, I assume Trigger registers this automatically when registering the trigger? Still, with the correct URL set in Shopify it fails to verify.

Here's an example piece of code that doesn't work:

import "@shopify/shopify-api/adapters/node"
import { Shopify } from "@trigger.dev/shopify"
import { client } from "../"

const shopify = new Shopify({
  id: "shopify",
  apiKey: process.env.SHOPIFY_API_KEY!,
  apiSecretKey: process.env.SHOPIFY_API_SECRET_KEY!,
  adminAccessToken: process.env.SHOPIFY_ADMIN_ACCESS_TOKEN!,
  hostName: process.env.SHOPIFY_SHOP_DOMAIN!
})

client.defineJob({
  id: "shopify/on-order-created",
  name: "Shopify: On Order Created",
  version: "0.1.0",
  trigger: shopify.on("orders/create"),
  run: async (payload, io, ctx) => {
    return { payload }
  }
})
@nicktrn
Copy link
Collaborator

nicktrn commented Dec 3, 2023

Hi @jaaneh, thanks for reporting this!

I've just tried to reproduce this with the latest @trigger.dev/shopify@2.2.10 but couldn't.

First thing to check would be that the integration and SDK packages are on 2.2.10, including the SDK. As you're self-hosting, the webapp should also be running the latest docker v2.2.17.

Seeing as Shopify doesn't have a way to insert the secret that Trigger gives you, and they instead give us one, I assume Trigger registers this automatically when registering the trigger?

Shopify uses the apiSecretKey for verification. The secret is shared between registration and verification via the new KV store. We've recently had to change the KV key encoding, so a mismatch between your package versions and the webapp image could explain the issue.

Otherwise, my guess would be the provided apiSecretKey is incorrect. I believe that verification would be the only thing to complain in that case.

To trigger re-registration you can just change the integration ID here:

const shopify = new Shopify({
  id: "shopify",
  ...
}

@jaaneh
Copy link
Contributor Author

jaaneh commented Dec 3, 2023

Hi @nicktrn. Appreciate the reply.

I am running 2.2.10 on the SDK, Express and Shopify packages. The self-hosted is also on the latest 2.2.17.

I've made sure the apiSecretKey is correct and matches. Please see below:

image
image

I've also tried to re-register it, by appending -dev

image

... but it seems to still fail the verification.

image

The trigger on Shopify is set to the DEV url from here:

image

with this setup

image

Here is the full code to my app.ts.

import express from "express"
import morgan from "morgan"

import { notFound, errorHandler } from "./handlers"

// Trigger
import "./trigger/jobs/shopify"
import { client } from "./trigger"
import { createMiddleware } from "@trigger.dev/express"

const app = express()

app.use(morgan("dev"))
app.use(express.json())
app.use(createMiddleware(client))

app.get("/", (_, res) => res.status(200).send({ status: "ok" }))

app.use(notFound)
app.use(errorHandler)

export default app

This is running the exact same job code as the example I gave above.

@jaaneh
Copy link
Contributor Author

jaaneh commented Dec 3, 2023

Ok, so changing from this

app.use(morgan("dev"))
app.use(express.json())
app.use(createMiddleware(client)) // <=

..to this

app.use(morgan("dev"))
app.use(createMiddleware(client)) // <=
app.use(express.json())

does the job. I assume the JSON parser is part of the issue.

@nicktrn
Copy link
Collaborator

nicktrn commented Dec 4, 2023

Thanks for the detailed walkthrough!

No need to be embarrassed, it's not immediately clear why this wouldn't work.

It's essentially due to requests from the platform not all having a json Content-Type. If that parser middleware runs before our client middleware, it will consume the body stream and set req.body = {} for non-JSON cases.

That being said, we should document this - don't think there's a workaround apart from adding middlewares that mutate the request only after the client middleware.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants