Amazon EventBridge Webhook Verification

Highlighted
Shopify Partner
5 0 0

We are looking to use Amazon's EventBridge service for pre-processing our webhooks, and I am struggling to manage the HMAC verification.

My first question would be: is it even necessary to verify webhooks in your AWS Event Bus settings? Since Shopify is a supported Partner event source maybe it can be confirmed that all events through such an Event Bus are verified by Amazon as being from Shopify. My thinking though is that the Event Bridge Rule only verifies the pattern, not the contents / sender.

If it is necessary to verify the webhooks, I am struggling to do so. My current assumption is that the raw request body is processed into JSON by the time my Lambda function handler receives it. Is there a way to access the raw request body in a Lambda function or to verify with an already parsed JSON string? Thanks in advance!

This was my attempt to verify with a Ruby Lambda function:

def lambda_handler(event:, context:)
    hmac_header = event["detail"]["metadata"]["X-Shopify-HMAC"]
    payload = event["detail"]["payload"]
    calculated_hmac = Base64.strict_encode64(OpenSSL::HMAC.digest('sha256', ENV['SHOPIFY_CLIENT_SECRET'], JSON.generate(payload)))
    
    if secure_compare(calculated_hmac, hmac_header)
        { statusCode: 200, body: JSON.generate(event) }
    else
        { statusCode: 401, body: "Unauthorized" }
    end
end

 

0 Likes
Highlighted
Shopify Staff
Shopify Staff
22 3 2

Hello, the event your receiving should be trustworthy, although as you said, the EvenBridge rule doesn't verify the sender. So though it's most likely trustworthy, it's best to verify using the HMAC in the payload as per https://shopify.dev/tutorials/manage-webhooks

I'm not entirely sure but looking at your code you may be doing an extra JSON conversion by adding JSON.generate(payload).

0 Likes
Highlighted
Shopify Partner
5 0 0

Thank you for the feedback. I have used that guide before to verify webhooks, but my understanding is that the examples given show what you can do when able to access the raw request body before it has been processed. For example the Sinatra demo uses `request.body.read` which reads the raw body as a string. I'm unsure how to do that using EventBridge.


@marcusradica wrote:

I'm not entirely sure but looking at your code you may be doing an extra JSON conversion by adding JSON.generate(payload).


`payload` seems to be a Ruby hash in this example and I believe `OpenSSL::HMAC.digest` requires a string input which is why I converted it to JSON. It causes an error when I do not convert the payload back into a string, but it's apparently not the same string used in the original digestion by Shopify to generate `HTTP_X_SHOPIFY_HMAC_SHA256`. 

0 Likes