Solving Shopify App Submission Woes: Compliance Webhooks & HMAC Signature Verification

Hey everyone,

I recently followed a really insightful discussion in the Shopify community that hit home for a lot of app developers. It was all about those tricky automated checks you face when submitting a public app – specifically, the ones for "Provides mandatory compliance webhooks" and "Verifies webhooks with HMAC signatures." If you've ever seen those fail, you know the frustration! Krishan_Dev_Yadav, an app developer working on "Nextbill," kicked off the thread, completely stumped as to why these checks were failing and where to even add the required compliance webhooks in the Dev Dashboard.

This is a super common hurdle, and luckily, the community came through with some fantastic, actionable advice. Let's break down what we learned and how you can tackle these challenges head-on.

Cracking the Compliance Webhook Code

First up, the "mandatory compliance webhooks" check. Krishan_Dev_Yadav, like many, was looking for a spot in the Dev Dashboard under "Versions and Configuration" to add these, but couldn't find one. And that's because, for apps created in the Dev Dashboard, it's not where you configure them directly!

Your New Best Friend: shopify.app.toml

The key takeaway from the discussion, brilliantly highlighted by hizachlee, is that these compliance webhooks – customers/data_request, customers/redact, and shop/redact – belong right in your app's shopify.app.toml file. This configuration file is where you define a lot of your app's core settings, and webhook subscriptions are definitely one of them.

Here's the exact snippet hizachlee shared that you'll want to add to your shopify.app.toml:

[[webhooks.subscriptions]]
uri = "/webhooks/customers/data_request"
compliance_topics = [ "customers/data_request" ]

[[webhooks.subscriptions]]
uri = "/webhooks/customers/redact"
compliance_topics = [ "customers/redact" ]

[[webhooks.subscriptions]]
uri = "/webhooks/shop/redact"
compliance_topics = [ "shop/redact" ]

Once you've added this to your shopify.app.toml, the next crucial step is to deploy your app with these changes. You'll do this using the Shopify CLI:

  • Open your terminal in your app's root directory.
  • Run: shopify app deploy

This command pushes your updated configuration to Shopify, making sure your app is subscribed to these essential compliance topics. These webhooks are super important for handling privacy regulations like GDPR, allowing merchants to request customer data or redact it when needed.

Mastering HMAC Signature Verification for Rock-Solid Security

The second big hurdle Krishan_Dev_Yadav faced, and another common one, was failing the "Verifies webhooks with HMAC signatures" check. This isn't just a compliance requirement; it's a fundamental security measure. Shopify sends a hash-based message authentication code (HMAC) with each webhook payload to ensure the request truly came from Shopify and hasn't been tampered with.

The Golden Rule: Verify the Raw Body First!

Both paulvatiche and hizachlee emphasized a critical point here: your endpoint must verify the X-Shopify-Hmac-Sha256 header against the raw request body. This is where many developers trip up. If your framework or server parses the JSON payload *before* you perform the HMAC verification, the signature simply won't match, even if your verification logic is otherwise perfect.

Your webhook handler needs to:

  1. Receive the incoming request.
  2. Access the raw, unparsed request body.
  3. Use your app's shared secret to compute your own HMAC from the raw body.
  4. Compare your computed HMAC with the one provided in the X-Shopify-Hmac-Sha256 header.

And here's the crucial part for passing the automated check:

  • If the signatures match, return a 200 OK HTTP status.
  • If the signatures do not match (meaning an invalid or tampered request), you must return a 401 Unauthorized HTTP status.

This 401 response for invalid signatures is non-negotiable for passing Shopify's checks, as paulvatiche pointed out.

Proactive Testing: Don't Just Wait and Wonder

Krishan_Dev_Yadav also asked about how long it takes for the automated checks to re-run and what requests they send. While the thread didn't give a specific timeline for Shopify's re-checks, the community offered excellent advice on how to *proactively test* your endpoints yourself, which is far more efficient than waiting.

Here's how you can test both valid and invalid signature cases:

  1. Testing a Valid Signature (Expect 200 OK):
    Use the Shopify CLI to trigger a compliance webhook to your public endpoint. This simulates a real webhook from Shopify.

    shopify app webhook trigger --topic customers/redact --address 
    

    Replace with the actual URL of your webhook endpoint. This should result in your server returning a 200 OK if your HMAC verification is correct.

  2. Testing an Invalid Signature (Expect 401 Unauthorized):
    To simulate an invalid signature, you'll need to use a tool like curl. Send a request to your endpoint with a made-up or incorrect X-Shopify-Hmac-Sha256 header.

    curl -X POST \\
      -H "Content-Type: application/json" \\
      -H "X-Shopify-Topic: customers/redact" \\
      -H "X-Shopify-Hmac-Sha256: THISISANINVALIDHMAC" \\
      -d '{"shop_id":12345,"shop_domain":"example.myshopify.com","customer":{"id":67890}}' \\
      
    

    Your server should respond with a 401 Unauthorized status for this request. This confirms your endpoint correctly rejects forged or invalid requests.

Remember paulvatiche's important note: the shopify app webhook trigger command is great for sending sample data, but it doesn't confirm your app is actually subscribed or that Shopify's internal system sees your configuration correctly. Always make sure your released app version's configuration contains all three compliance topics and the public endpoint URLs you expect, and that those URLs are indeed accessible and correctly configured.

So, there you have it! The community's wisdom points to a clear path: correctly define your compliance webhooks in shopify.app.toml and deploy, then meticulously implement HMAC verification on the raw request body, ensuring you return the correct HTTP status codes (200 for valid, 401 for invalid). Proactive testing with the CLI and curl will save you a ton of time and guesswork. It's a testament to how helpful the Shopify developer community can be when navigating these specific technical challenges.

If you ever find yourself deep in developer-specific questions, Laza_Binaery also made a good point about checking out the Shopify Developer Community Forums. While the main Shopify community is fantastic for merchants, the developer forum is often where you'll find more direct input from fellow developers and even some Shopify team members on these more intricate API and app development topics. Happy building!

Share:

Start with the tools

Explore migration tools

See options, compare methods, and pick the path that fits your store.

Explore migration tools