Securing Webhooks

When receiving webhook payloads from Tradier you can verify the digital signature of the webhook that you receive on your endpoint. By default, Tradier will use your Client Secret to add a signature that is delivered via the x-webhook-signature header along with webhook payloads.

For an added measure of security, when creating a webhook you can define a custom secret that is used to sign the webhook payload in lieu of your Client Secret.

Verifying Webhook Payloads

Tradier uses HMAC-SHA256 to compute the hash that is delivered in the header. For example, let’s assume you’ve set the secret for a webhook to my_webhook_secret. The body of the webhook payload is hashed and the resulting hash is delivered in the x-webhook-signature header:

HTTP

POST /yourtradier/webhook HTTP/1.1
Content-Type: application/json; charset=utf-8
Host: yourhost.com
x-webhook-signature: 617b9e5b2fb70b0107cb1f59a7d13b096576de5702306c57c63315787e47a145
Connection: close
Content-Length: 96

{"applicationId": 5,"clearingAccount": "1234","action": "SUBMITTED","email": "test@example.com"}

To verify the payload, you would then use the secret and the body of the webhook to generate a local hash that you could then use for comparison:

Ruby

body = '{"applicationId": 5,"clearingAccount": "1234","action": "SUBMITTED","email": "test@example.com"}'
secret = 'my_webhook_secret'
sig = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), secret, body)

# ensure that the signatures match
request.headers['x-webhook-signature'] == sig

Rack::Utils.secure_compare(sig, request.headers['x-webhook-signature'])

Note that it is best not to use a equivalency checker like == but rather to find a library that can do a secure comparison of the two values and lessens the risk of a timing attack.