- HOME
- Security and Privacy
- How can you secure your webhooks?
How can you secure your webhooks?
- Published : October 4, 2023
- Last Updated : October 16, 2024
- 1.5K Views
- 8 Min Read
Let's start off by setting the context. A webhook is an HTTP request used to send event-driven notifications from one application to another. For example, webhooks in your email provider can relay the notification of email delivery to your application. You can read our detailed article on webhooks here.
Webhooks are a great way to transfer event information between applications. They are instant, effective, and don’t require constant polling, but they’re vulnerable to attacks. Webhook requests are sent to public URLs that can be accessed by any unauthorized and malicious person.
These threats could come in many forms, such as impersonated messages, tampered messages, or completely unauthorized requests. With the threats coming in different shapes and sizes, the security also must be multi-fold. There are multiple ways to secure a webhook, and it’s best to use a combination of these security measures to obtain maximum security. In this article, we’ll talk at length about the different security measures available to secure and protect your webhook.
Encrypt the data
Webhook requests are often made in HTTP protocol. In this protocol, information is transported in plain text, which means anyone who intercepts the message will be able to read it.
Before making sure that the message cannot be intercepted, you can take the simplest webhook security measure to ensure that even if it is intercepted, the message isn't readable.
You can do this by using the HTTPS protocol instead of HTTP. It adds an additional layer of security to HTTP. All data transferred through HTTPS is encrypted, making it difficult to interpret for attackers. You can do this by updating your client to HTTPS using a SSL certificate.
Implement authentication tokens or basic authentication
As previously mentioned, webhook endpoints are public URLs that can be accessed by anyone. Because of their nature, they’re vulnerable to unauthorized requests. You need a security measure in place that will vet the sender to ensure the request originates from the right place.
To verify the source of the request, you can use authentication tokens or basic authentication. It’s one of the simplest ways to authenticate the source, but it does come with its own shortcomings.
You can add an authentication token to the header of your webhook request that the receiving application can verify to ensure the authenticity of the request. If the token matches, the request is valid. If you're a webhook provider, you can make it easier for your clients by providing them the provisions for authentication tokens or keys.
Much like authentication tokens, you can also use basic authentication to verify the request source. The webhook endpoint has a specific username and password that you have to add to your webhook header. On receiving the request, the listening application will verify the username and password before accepting the request.
Alternatively, you can also have the receiving application whitelist the IP address of valid requests to eliminate requests originating from other IP addresses. However, this might not work well for users who prefer flexibility with their originating IP addresses.
All three of these methods are based on a shared secret. While they’re good security measures, they fall short of being airtight because the secrets are shared in plain text. Should the attacker intercept the username and password or the authentication token, this security measure would fail. Additionally, while these methods help authenticate the source, they don’t ensure message integrity. Hence, these measures are best used alongside other measures mentioned in this article.
Sign webhooks with HMAC
Hash-based Message Authentication Code (HMAC) is the most popular method of securing a webhook by a good margin. As the name suggests, it uses a hash algorithm to create a unique signature for the webhook request to secure it. The exact type of hash algorithm used is agreed upon by the sender and receiver of the webhook. Here’s how it works.
On the sender's end:
Signature creation: The webhook request sender generates the signature. The payload of the webhook and the secret code are combined together and then a hash algorithm, like SHA1 or SHA256, is used to encode this combination to create the signature.
Attach signature: The signature is then added to the webhook header and the request is sent.
On the receiver's end:
Re-create the signature: On arrival of the request, the receiver uses the agreed-upon hash algorithm and secret code on the content to re-create the signature.
Verify the match: The re-created signature is compared with the signature that came with the webhook header. If both signatures match, the request is considered valid and untampered with.
HMAC signing is a great way to ensure that the webhook request has not been tampered with. It has some significant advantages over authentication tokens and the basic authentication method:
The shared secret isn’t transported with the request, making it impossible for any attacker to gain access to it. Only the signature generated using the secret is sent with the request.
This method helps with the authentication of the sender as well as ensures that the request content hasn’t been tampered with.
While HMAC is a very good security measure, it only works well when implemented well. Here are some best practices for both providers and users to follow while implementing HMAC signing for webhooks:
Ensure simplicity: Webhook providers should avoid adding steps that increase the complexity of signature generation without improving the security of the process.
Good documentation: Providers should give good, detailed documentation to help the users with the implementation. Ensure that each step is well explained, and all of the required information is presented to the user.
Unique secrets: While signing webhooks, use unique secrets that don’t coincide with credentials of other accounts or systems. It helps to keep the secret code random and unassociated to identifiers.
Key rotation: Both providers and users need to give provisions for key rotation. Much like any secret keys or codes, it’s always better to periodically change the key used for HMAC signing to avoid compromise. The implementation should allow for the keys to be rotated without any interruption to the request during sending and receiving.
Forward compatibility: Any security process should be prepared for versioning. HMAC should be implemented with the ability for upgrades to more advanced hash algorithms or signing processes.
Add timestamps to requests
Attackers don't always intercept a message or impersonate a request. Sometimes they simply re-create the request in its entirety at their convenience. These attacks are called replay attacks. While in most cases sending the request twice wouldn't do much harm, in other cases where a significant action is triggered by the webhook, replay attacks can be extremely harmful.
To prevent these replay attacks, you can add timestamps to your requests. These timestamps are best used in combination with HMAC signing, in which case, apart from the request body and secret code, a timestamp is also added before the hash algorithm is used to encode the signature.
When the receiver gets the request, they decode the timestamp. If the request has been received within an acceptable duration from the timestamp (say five minutes), the request is accepted. If significant time has elapsed after the timestamp, the receiver rejects the request.
Use asymmetric key encryption
An asymmetric key encryption is very similar to HMAC. It only varies in the aspect that instead of one secret code and one hashing algorithm, in asymmetric encryption, there are two keys—a public key and a private key. One is used by the sender to encrypt the data, and the other is used by the receiver to verify the data.
Here’s how it works:
The sender uses its private key to create a signature that’s added to the header of the webhook request.
On receiving the request, they run the public key, the request content and signature in the header through a verifier like the Elliptical Curve Digital Signature Algorithm (ECDSA) or the Rivest-Shamir-Adleman algorithm (RSA).
If the verifier returns a positive, the request is accepted.
The main difference between this and HMAC is that, in HMAC, the signature is re-created whereas here, it’s run through a verifier to check its authenticity. Other than that, the implementation best practices suggested for HMAC also applies to asymmetric encryption.
Mutual authentication with TLS
While all of the previous security measures can ensure message and sender authenticity, one missing piece is the verification of the receiver. Much like attackers creating unauthorized requests, they could route authentic requests to unauthorized destinations. This could lead to sensitive information ending up in the hands of the wrong people.
Mutual TLS is the perfect way to ensure that there is authentication on both sides. The receiver verifies the sender and the sender verifies the receiver in a single authentication process.
Before the webhook request is sent, a TLS handshake is initiated between the sender and receiver where each side is required to show their TLS certificates. After the certificates have been authenticated, the webhook request is sent through. If one of the parties is unauthorized, they won’t request the TLS certificate, and the authentication will fail.
This is a great way to protect your webhook, but it’s difficult to configure and might not be absolutely necessary for all webhooks.
In a nutshell, here are the available security measures and what they do:
Data encryption (e.g., HTTPS): Reduces the readability of data during transit.
Authentication tokens and basic authentication: Helps verify the sender.
HMAC: Helps verify the sender and ensure that the request hasn't been tampered with, using hash algorithms.
Asymmetric encryption: Helps verify the sender and the message’s integrity using public and private key encryption mechanisms.
Timestamps: Best used in combination with HMAC or asymmetric encryption and helps avoid replay attacks.
Mutual TLS: Helps authenticate both sender and receiver using mutual authentication
A summary of best practices
We’ve seen the different security measures available to secure your webhooks. Here are some things to keep in mind irrespective of the authentication method you choose to use.
For senders:
Avoid unnecessary complexities in security measures like signature generation.
Provide detailed and accurate documentation for implementation.
If you're a webhook provider, give a provision to test the webhook.
Choose an appropriately random secret code to be used in these authentication methods.
Store the key with utmost safety and precaution.
Make accommodations for key rotation and future upgrades.
Ensure you implement the highest version of security available, such as the most secure algorithm.
If convenient, provide an IP that your webhook requests will come from.
For receivers:
Ensure that you’re making use of all of the security features available from the sender's side.
Accept requests through protected HTTPS protocols.
Safeguard your secret codes while in storage.
Rotate secrets/keys and upgrade processes when possible.
Restrict the requests you can receive wherever possible through IP restriction and other similar measures.
Call back the sender service from a different channel if the API endpoint is provided in the header to verify the sender.
Zoho ZeptoMail is a transactional email service that provides webhooks along with great security features to keep them protected against threats and attacks. Take a look at our webhooks documentation here.