How to secure Twilio webhook URLs in Node.js
Time to read: 3 minutes
How to secure Twilio webhook URLs in Node.js
Twilio’s APIs allow developers to reinvent communications with things like programmable phone calls, SMS or intelligent chatbots. Developers can build applications to interact with their users and react to their responses. To respond to events like incoming messages, you can define a webhook URL. A webhook is an HTTP request that Twilio performs to find out what the reaction to a Twilio even like an incoming SMS should be. Your defined HTTP endpoints have to respond with a Twilio-understandable configuration language called TwiML (Twilio Markup Language).
These endpoints can be hosted anywhere as long as they’re available publicly and accessible by Twilio’s infrastructure.
Three ways to secure your webhook URLs
Let’s assume you built a rating application that allows users to rate an event they’re at by sending an SMS to a certain number. Every incoming SMS to your number triggers a webhook to your infrastructure that can write the included data to disk.
Unfortunately, an evil hacker found your webhook HTTP endpoint and recognizes the responded TwiML response as Twilio configuration. The hacker is now able to make requests to your application, which messes with the result of your event rating and makes it useless.
Securing your webhook URLs is always recommended. But as the Twilio docs describe, it’s crucial if you expose sensitive data or mutate existant datasets like in our rating example. How can you make sure only Twilio is interacting with your endpoints?
First, make sure you’re using HTTPS. Man-in-the-middle attacks are a common risk, and if you’re not serving your Twilio configuration over a secure connection, you can never be sure that a third party didn’t alter it. What you could do additionally is to secure your endpoints with HTTP authentication. This way your webhook URLs are not accessible without a username/password combination in the first place.
A third option is to validate if the incoming requests were sent by Twilio using the X-Twilio-Signature
header which is the core of this article. Let’s have a look at how this works in detail!
The X-Twilio-Signature
header
When Twilio sends a request to your defined webhook URL, it will include the x-twilio-signature
header. This header is an encoded string representing the request URL and the sorted request parameters. The resulted string is then signed using HMAC-SHA1 using your AuthToken as the key. The AuthToken is crucial here because its value is only accessible to Twilio and yourself. A third party can not generate the same hashed Twilio signature without having access to it.
To validate incoming requests, you can perform the same signature procedure and compare if your generated signature and the sent signature match. If they do, you can be sure that Twilio sent the request you received.
Sidenote: in case you’re using serverless functions via Twilio Runtime, you might have seen the access control setting, which enables Twilio signature validation for every incoming request.
X-Twilio-Signature
validation using the Twilio Node.js helper library
To make it as easy as possible, the Twilio Node.js helper library not only provides you with functionality to build TwiML responses or interact with the API endpoints, it also includes the feature to validate requests.
To get started, make sure you installed the library.
After you installed it, you can use the validateRequest
method that is exposed to the exported Twilio object. The method accepts four arguments:
- your Twilio AuthToken
- the
x-twilio-signature
header included in the incoming request - the URL your HTTP is accessible at
- the included request parameters
In Node.js you can use the validateRequest
method in express as follows:
validateRequest
is the recommended way to validate incoming webhooks. It works with any framework out there and I hope you start securing your endpoint URLs today. If you’re using express, too, the Twilio library also provides a middleware to make request validation with this popular framework easier.
Things happening under the hood
If you’re curious how to generate the signature yourself, you can have a look at the docs that explain it in detail or have a look at the following example code:
Not every request comes from where you think it comes from
I hope this article brings light into the question of how you can make sure that the request hitting your webhook URLs are really Twilio’s and not just a person tinkering with your infrastructure. If you want to see how you can make your webhook URLs more secure using express, you can have a look at this tutorial. You can also have a look at how to secure your webhooks in Ruby or Python. And that’s it friends, stay safe! See you next time!
If you have questions or want to say “Hi” you can reach me under the following channels:
- Email: sjudis@twilio.com
- Github: stefanjudis
- Twitter: @stefanjudis
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.