title: Verify Shopify webhook
body: <p>I believe that to have a Shopify webhook integrate with a Rails app, the Rails app <a href="https://github.com/rails/rails/issues/3041" rel="nofollow noreferrer">needs to disable the default <code>verify_authenticity_token</code> method</a>, and implement its own authentication using the <code>X_SHOPIFY_HMAC_SHA256</code> header. The <a href="https://help.shopify.com/api/getting-started/webhooks#verify-webhook" rel="nofollow noreferrer">Shopify docs</a> say to just use <code>request.body.read</code>. So, I did that:</p>
  
  <pre><code>def create
      verify_webhook(request)
  
      # Send back a 200 OK response
      head :ok
  end
  
  def verify_webhook(request)
      header_hmac = request.headers["HTTP_X_SHOPIFY_HMAC_SHA256"]
      digest = OpenSSL::Digest.new("sha256")
      request.body.rewind
      calculated_hmac = Base64.encode64(OpenSSL::HMAC.digest(digest, SHARED_SECRET, request.body.read)).strip
  
      puts "header hmac: #{header_hmac}"
      puts "calculated hmac: #{calculated_hmac}"
  
      puts "Verified:#{ActiveSupport::SecurityUtils.secure_compare(calculated_hmac, header_hmac)}"
  end
  </code></pre>
  
  <p>The Shopify webhook is directed to the correct URL and the route gives it to the controller method shown above. But when I send a test notification, the output is not right. The two HMACs are not equal, and so it is not verified. I am fairly sure that the problem is that Shopify is using the entire request as their seed for the authentication hash, not just the POST contents. So, I need the original, untouched HTTP request, unless I am mistaken.</p>
  
  <p><a href="https://stackoverflow.com/questions/2850256/how-do-i-see-the-whole-http-request-in-rails">This</a> question seemed like the only promising thing on the Internet after at least an hour of searching. It was exactly what I was asking and it had an accepted answer with 30 upvotes. But his answer... is absurd. It spits out an unintelligible, garbled mess of all kinds of things. Am I missing something glaring?</p>
  
  <p>Furthermore, <a href="http://www.rubypigeon.com/posts/examining-internals-of-rails-request-response-cycle/" rel="nofollow noreferrer">this article</a> seemed to suggest that what I am looking for is not possible. It seems that Rails is never given the unadulterated request, but it is split into disparate parts by Rack, before it ever gets to Rails. If so, I guess I could maybe attempt to reassemble it, but I would have to even get the order of the headers correct for a hash to work, so I can't imagine that would be possible.</p>
  
  <p>I guess my main question is, am I totally screwed?</p>