Using a Webhook Secret
March 1, 2023Webhooks include the ability to define a “secret” parameter, which will pass along with your webhook as a header called “X-Spark-Signature”. This can be used to validate a request is coming from the Webex platform and not from some other origin – more info can be found at the bottom of this page.
In this blog, we’ll walk you through using the secret field, so you can start locking down your webhooks ASAP.
First, you’ll need to create a webhook.
Note the "secret" field in the list of options; to make it easy, we’ll use the passphrase listed in the example and set it to:
somesupersecretphrase
Next you’ll need to code up some logic that checks the secret when the webhook’s data is received. The following script shows very simple validation – just prints out a true if the secret matches. Here’s the Python code:
import itty3
import hashlib
import hmac
app = itty3.App()
@app.post('/')
def index(request):
body="OK"
"""
When messages come in from the webhook, they are processed here.
X-Spark-Signature - The header containing the sha1 hash we need to validate
request.body - the Raw JSON String we need to use to validate the X-Spark-Signature
"""
raw = request.body
# Let's create the SHA1 signature
# based on the request body JSON (raw) and our passphrase (key)
hashed = hmac.new(key.encode(), raw, hashlib.sha1)
validatedSignature = hashed.hexdigest()
print('validatedSignature', validatedSignature)
print('X-Spark-Signature', request.headers.get('X-Spark-Signature'))
print('Equal?', validatedSignature == request.headers.get('X-Spark-Signature'))
return app.render(request, body)
# Replace this with the secret phrase you used in the webhook creation
key = "somesupersecretphrase"
app.run(addr='0.0.0.0', port=10010)
which can also be grabbed from Github.
Note the “key” field is the secret defined earlier when the webhook was created, which if it matches what’s sent in the webhook, will return ‘true’.
This app alone won’t do much – all it’s going to do is confirm “Yep, that’s the right secret!” and then end. But if we combo it with our Bot example | (Github Repo) then we can validate the secret and use it in an if / else statement. If the secret matches, keep going, if it does not, end immediately. The complete code combining the above validation script and the bot script can be found Github as well.
From that app, here’s a snippet showing the relevant logic using validation:
raw = request.body
# Let's create the SHA1 signature
# based on the request body JSON (raw) and our passphrase (key)
hashed = hmac.new(key.encode(), raw, hashlib.sha1)
validatedSignature = hashed.hexdigest()
print('validatedSignature', validatedSignature)
print('X-Spark-Signature', request.headers.get('X-Spark-Signature'))
if validatedSignature == request.headers.get('X-Spark-Signature'):
# Run the app
else:
print("Secret does not match, verboten!")
You can expand on all of the logic extensively, but for the basic use of a secret in a functional bot app, this covers what you need to know. If you have any questions, please contact devsupport@webex.com and we’ll be happy to help!