title: Hashing Plaid Request Body Webhook
body: <p>I am trying to verify a webhook sent from Plaid's <a href="https://plaid.com/docs/#webhook-verification" rel="noreferrer">API</a>. Every webhook request is sent with a 'plaid-verification' header which is a JSON Web Token.</p>
  
  <p>The steps required to validate are:</p>
  
  <ol>
  <li>Extract JWT from request header</li>
  </ol>
  
  <p><code>signed_jwt = eyJhbGciOiJFUzI1NiIsImtpZCI6IjZjNTUxNmUxLTkyZGMtNDc5ZS1hOGZmLTVhNTE5OTJlMDAwMSIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1OTA4ODcwMDEsInJlcXVlc3RfYm9keV9zaGEyNTYiOiJiNjNhMDdiNTQ3YjAwZjk5MjU0N2Y2YmJjOGQ5YWNjNjFhOGNjZWUxMzhiYzgyZjQ0YTZiYWEwOTY4M2E1ZDBmIn0.OOKvIihgqCj7Qrb2bmz7T3t7uK-0JyjiEqL2s1kWeJBM4MMmjaHKK8GmU_z91QolBWMzvPgs718EElY-rE3cwQ</code></p>
  
  <ol start="2">
  <li>Extract JWT header value without validating the signature, which looks like this:</li>
  </ol>
  
  <pre><code>    {
        "alg": "ES256",
        "kid": "6c5516e1-92dc-479e-a8ff-5a51992e0001",
        "typ": "JWT"
      }
  </code></pre>
  
  <ol start="3">
  <li>Extract the <code>kid</code> and POST to <code>/webhook_verification_key/get</code></li>
  </ol>
  
  <pre><code>    POST /webhook_verification_key/get
      {
          "client_id": "MY_CLIENT_ID"
          "secret": "MY_SECRET_ID"
          "key_id": "6c5516e1-92dc-479e-a8ff-5a51992e0001"
      }
  </code></pre>
  
  <p>The response is:</p>
  
  <pre><code>{
    "key": {
      "alg": "ES256",
      "created_at": 1560466143,
      "crv": "P-256",
      "expired_at": null,
      "kid": "6c5516e1-92dc-479e-a8ff-5a51992e0001",
      "kty": "EC",
      "use": "sig",
      "x": "35lvC8uz2QrWpQJ3TUH8t9o9DURMp7ydU518RKDl20k",
      "y": "I8BuXB2bvxelzJAd7OKhd-ZwjCst05Fx47Mb_0ugros"
    },
    "request_id": "HvfCtrDLG1ihcp7"
  }
  </code></pre>
  
  <ol start="4">
  <li>Interpret <code>key</code> as a JSON Web Key, validate that the signature of the JSON Web Key is valid, and extract the payload (using jose python library)</li>
  </ol>
  
  <pre><code>claims = jwt.decode(signed_jwt, key, algorithms=['ES256'])
  
  claims = {
               "iat": 1590887001, 
               "request_body_sha256": "b63a07b547b00f992547f6bbc8d9acc61a8ccee138bc82f44a6baa09683a5d0f"
           }
  </code></pre>
  
  <ol start="5">
  <li>Compute the SHA-256 of the request body and ensure that it matches <code>claims['request_body_sha256']</code>:</li>
  </ol>
  
  <p>Body is in a file body.json</p>
  
  <pre><code>{
      "error": null,
      "item_id": "yxQbxDjnD8hr69pKbQpbcKeVn3GL9QuyA7NV3",
      "new_transactions": 390,
      "webhook_code": "HISTORICAL_UPDATE",
      "webhook_type": "TRANSACTIONS"
  }
  </code></pre>
  
  <p>Compute SHA-256 of body.json</p>
  
  <pre><code>f = open('body.json')
  body = json.load(f)
  f.close()
  
  m = hashlib.sha256()
  m.update(json.dumps(body).encode())
  body_hash = m.hexdigest()
  print(body_hash)
  
  body_hash = 'efbb5274864518f7eb3834125d9bcdb95fb03066d3d1bed3ebcc6163d8dc3579'
  </code></pre>
  
  <p>The body hash in the example above does not equal the body hash received from Plaid. There's 2 possible problems here:</p>
  
  <ol>
  <li>Plaid isn't sending the correct body hash (unlikely)</li>
  <li>The hash method I'm using to hash the body is not the same as Plaid's method</li>
  </ol>
  
  <p>Is there something I'm missing here? Perhaps the request body is encoded differently on my end? I'm using Node.js and Express in production but I made a Python script to follow the method Plaid outlined <a href="https://support.plaid.com/hc/en-us/articles/360041410794" rel="noreferrer">here</a>, but I'm still not getting the correct hash. I'm honestly out of ideas.</p>