Axle Health currently supports two types of authentication for webhooks.
Authentication Tokens
We can set api keys of your choice in the Authentication header of our requests. Currently supported authentication schemes currently include:
If you would like to use another token based authentication token method, please reach out to the Axle team for support.
Webhook Signature
Axle Health optionally supports sending signed webhook signatures in the Axle-Signature
HTTP header. You can verify this signature manually to ensure that the webhook was not sent by an un-authorized third party.
Steps to Verify Signature
Step 1: Extract timestamp and signature from Axle-Signature
Both the timestamp and the signed signature are included in the Axle-Signature header.
Example:Axle-Signature: t=<UNIX_TIMESTAMP_IN_SECONDS>,v1=<SIGNATURE>
Step 2: Generate the expected signature
To generate the signature, create an HMAC using SHA-256. The key to use is the key provided by Axle Health. The message format for use in the HMAC is as follows:
message = <UNIX_TIMESTAMP_IN_SECONDS>.<HTTP_BODY_AS_STRING>
Step 3: Verify the signature
If your generated signature is the same as the signature retrieved from the Axle-Signature header, then you have successfully verified the authenticity of the received webhook.
Security Notes
There are two attack vectors to be aware of and to guard against when using webhook signatures.
Timing Attacks:
To guard against timing attacks, it is advised that you use a constant time comparison function when comparing your generated signature to the signature sent in the Axle-Signature header.
Replay Attacks
Replay attacks can happen when an attacker intercepts webhooks sent to you and resends it to you at a different time. To guard against this, the timestamp is included in the webhook signature so that the timestamp cannot be changed without invalidating the signature. As is required by your own security needs, you can choose a tolerance window in which you will accept incoming webhooks.
Code Samples
import hmac
from hashlib import sha256
from rest_framework.response import Response
webhook_secret = '<WEBHOOK_SECRET_KEY>'
def webhook_handler(request):
timestamp, signature = get_timestamp_and_signatures(request.META['HTTP_AXLE_SIGNATURE'])
body = request.body.decode('utf-8')
message = f'%{timestamp}.{body}'
gen_signature = generate_signature(
webhook_secret,
message
)
if hmac.compare_digest(signature, gen_signature):
# Your Logic here
return Response()
else:
# Raise exception and handle error
return Response(status=403)
def generate_signature(key, message):
mac = hmac.new(
key.encode('utf-8'),
msg=message.encode('utf-8'),
digestmod=sha256
)
return mac.hexdigest()
def get_timestamp_and_signatures(header):
(t, signature) = header.split(',')
t = t.split('=')[1]
signature = signature.split('=')[1]
return t, signature