Issues with Shopify Webhook HMAC verification : Failing Automated Checks

Topic summary

A developer is experiencing failures with Shopify’s automated HMAC webhook verification checks, despite manual testing (via Postman) working correctly.

Technical Setup:

  • App URL: https://laravel.***.io/
  • Using PHP for HMAC verification with hash_hmac('sha256') and base64_encode()
  • Comparing calculated HMAC against HTTP_X_SHOPIFY_HMAC_SHA256 header

Key Issues Identified:

  • Discrepancy between manual and automated verification results
  • Potential problems with case sensitivity or input consistency
  • Questions about known issues with automated HMAC checks

Proposed Solution:
A community member suggested ensuring:

  • Raw POST body is retrieved using file_get_contents('php://input')
  • HMAC header is correctly accessed via $_SERVER['HTTP_X_SHOPIFY_HMAC_SHA256']
  • CLIENT_SECRET is accurate
  • Using hash_equals() for secure comparison

Current Status:
The original poster requested clarification on the proposed solution, as automated checks continue to fail. The discussion remains open with unresolved verification issues.

Summarized with AI on November 8. AI used: claude-sonnet-4-5-20250929.

Hi everyone,

I’m implementing webhooks in my Shopify app (installed at [ https://laravel.***.io/]). I’ve managed to get webhooks working manually (e.g., through Postman) and they’re triggering correctly. However, during automated checks (like Shopify’s app review process), the “Implement an HMAC signature to verify webhooks” check is failing.

Here’s what I’ve done:

My app URL is: [ https://laravel.***.io/]

My Allowed redirection URL(s): [ https://laravel.***.io/shopifyGenerateToken]

I’ve implemented HMAC verification using PHP and I’m comparing the received HMAC header with a calculated one.

My code:

<?php define('CLIENT_SECRET', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); function verify_webhook($data, $hmac_header) { $calculated_hmac = base64_encode(hash_hmac('sha256', $data, CLIENT_SECRET, true)); return hash_equals($calculated_hmac, $hmac_header); // Consider using strcmp for basic verification } $hmac_header = $_SERVER['HTTP_X_SHOPIFY_HMAC_SHA256']; $data = file_get_contents('php://input'); $verified = verify_webhook($data, $hmac_header); if ($verified) { // Process the webhook http_response_code(200); } else { http_response_code(401); } ?>

The Issue:

While manual testing works, automated checks are failing. This leads me to believe there might be a discrepancy in the way I’m handling HMAC verification, potentially related to case sensitivity or input consistency.

Questions:

Is there a known issue with HMAC verification during automated checks?

Could the case sensitivity of the HMAC signature be a factor?

Are there any best practices for handling webhook verification within automated environments?

I’d appreciate any guidance or insights on how to resolve this issue. Thanks!

Hello, @hashcrypthash_1

To fix the HMAC verification issue for Shopify webhooks, ensure you correctly handle case sensitivity and data consistency. Here’s a refined version of your code:

php
Copy code

<?php define('CLIENT_SECRET', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); function verify_webhook($data, $hmac_header) { $calculated_hmac = base64_encode(hash_hmac('sha256', $data, CLIENT_SECRET, true)); return hash_equals($calculated_hmac, $hmac_header); } $hmac_header = $_SERVER['HTTP_X_SHOPIFY_HMAC_SHA256']; $data = file_get_contents('php://input'); $verified = verify_webhook($data, $hmac_header); if ($verified) { // Process the webhook http_response_code(200); } else { http_response_code(401); } ?>

Key Points:

Use the raw POST body with file_get_contents(‘php://input’).
Ensure the HMAC header is correctly retrieved: $_SERVER[‘HTTP_X_SHOPIFY_HMAC_SHA256’].
Verify CLIENT_SECRET is correct.

This should help your webhook verification pass both manual and automated checks.

Best Regard,
tanya635rosario
Lowes Life

Can you provide some results because in the solution that you provided the checks are failing.