What Are the Webhook Authentication Strategies?

In a previous article, we concluded that one of the major vulnerabilities of the webhook design is the lack of authentication on both ends of the communication channel. A consumer cannot verify that it’s receiving a webhook from the expected source; in the same vein, a webhook producer cannot verify the consumer.

To solve this problem, we need an authentication system in place for webhooks to be sent to the right destination and ensure the source is verified. In this article, we discuss the webhook authentication strategies available to developers today. Then I compare each method to help you make an informed decision when selecting an authentication strategy.

How do you secure a webhook?

Before diving into the authentication strategies for webhooks, let’s do a quick recap of webhook security vulnerabilities and security methods to mitigate them. The table below maps the security vulnerabilities we have identified along with solutions discussed in our webhook security checklist article.

Security VulnerabilitySolution
No verification for the source and destination of a webhookAuthentication
Webhook data is exposed in transitTLS/SSL encryption
Webhook data is not verifiedSignature verification
No restriction on where webhook can come fromAuthentication/Mutual TLS
Webhook requests can be duplicatedCryptographic nonce

One interesting observation from the table above is the number of times authentication appears as a solution. At least 3 out of the 5 vulnerabilities listed in the table can be solved through authentication.

This is why authentication is so important when it comes to securing webhooks. In the next section, we’ll take a look at the different ways we can achieve this.

What are the webhook authentication strategies?

Basic authentication

Basic authentication is one of the oldest, simplest ways of verifying webhooks. It makes use of a username and password for webhook producers to be authenticated when sending webhooks to an HTTP endpoint (webhook URL). Let’s take a look at how basic authentication works with webhooks by running through the steps.

  1. The developer of the destination application submits their username and password to the webhook provider.
  2. The provider first sends a request with no Authorization header. This request is rejected with a 401 status code by the destination endpoint which then sends back an authentication challenge using the WWW-Authenticate header.
  3. The producer then combines the username and password with a colon (:) and sends a base64 encoded version of the string in the Authorization header of the request to authenticate the request using the format:
Authorization: Basic {base64(username:password)
  1. The destination endpoint receives the authenticated requests, verifies the credentials, and if valid, allows the webhook. If the credentials are not valid, the webhook is rejected.

One of the major webhook providers that supports basic authentication is Twilio. Twilio also supports digest authentication, which is more complex and was designed to replace basic authentication by providing more protection features.

Okta also uses basic authentication for authorizing webhook requests. Instead of submitting your username and password directly to Okta, you perform the username:password combination and encode it in base64, then give the value to Okta as an authorization secret.

Verification (bearer) token and custom headers

Another type of authentication strategy involves the passing of a secret string in the request header. This string is given to the webhook producer after successful authentication and used to verify each webhook request.

Token authentication

One standard method of this approach is token authentication. This is an OAuth verification protocol that allows users to verify their identity on a web application, receive an access token and verify each request to the web app with the access token. The authenticated request uses the Authorization header to send the token using the format below:

Authorization: Bearer {token}

Webhook consumers can use this strategy to authenticate webhook requests arriving at the webhook URL.

For webhook producers, unlike with basic authentication, the implementation of token-based authentication is not so widespread. This might be due to the fact that token-based authentication has a more complicated flow and often involves an authorization server to supply the tokens.

Services like SparkPost and Akamai Identity Cloud have full support for webhook token authentication. This includes allowing users to configure an authorization server by entering its client ID, client secret, and the URL of the server from which the token will be retrieved.

Other webhook providers like Zapier and JIRA allow you to add an authorization header that sends each time a webhook is triggered. You can use this to insert an authentication token to your requests so that your webhooks can be successfully authenticated on your API endpoint.

Custom headers

A lesser-used method of authentication involving a secret string being passed from a webhook producer to a consumer is the use of custom headers. Webhook providers like Okta and ContentStack give you the ability to define custom HTTP headers when setting up your webhook.

These headers are sent along with your webhook and they are used by the webhook consumer to authenticate webhook requests, and reject webhooks that do not contain the custom headers.

Signature verification

Signature verification shines mostly in its ability to validate the payload of the webhook. Authentication of source and destination of webhooks is implicit because both ends are involved in the verification process. Signature verification is also the only authentication strategy with a method for preventing replay attacks.

Let’s take a look at how signature verification works.

  1. A secret key is known by both the webhook producer and consumer.
  2. When sending a webhook, the producer uses this key and a cryptographic algorithm (e.g. HMAC) to create a cryptographic hash of the webhook payload. This is the webhook’s unique signature.
  3. The signature is sent in a custom header along with the webhook request. Sometimes, the type of algorithm used is also sent.
  4. When the webhook arrives at the webhook URL, the receiving application takes the webhook payload and uses the secret key and the cryptographic algorithm to calculate the signature.
  5. The calculated signature is then compared with that sent by the producer in the custom header. If there is a match then the request is valid, and if not the webhook is rejected.

This process enables developers to verify the integrity of the webhook payload and the authenticity of the webhook producer. To learn more, check out this guide where we get more practical in showing how you can implement signature verification, the right way, in your application.

Preventing Replay attack

As I mentioned earlier, one major advantage to using signature verification is its ability to prevent webhook replay attacks. A replay attack occurs when an attacker gets hold of an authenticated request and repeats it, thereby causing the webhook’s effect to be duplicated in the receiving application.

To prevent replay attacks, signature verification allows you to add a timestamp that can be used to expire the webhook after a certain period of time, for example 2 minutes. This time can be adjusted based on your security requirements.

An example of a webhook provider that does this by default is Stripe. Stripe adds an expiration timestamp in a Stripe-Signature header to the webhook. This timestamp is also verified along with the other contents of the payload which means that the attacker cannot manipulate it.

When the webhook hits the webhook URL, it is checked against the current time to see if it’s still valid for use. If the timestamp is too old, the webhook is rejected.

Which webhook authentication strategies should I use?

Now that we are familiar with the different strategies that can be used to authenticate webhooks, let’s take a look at their capabilities side by side so you can decide the one that best suits your use case.

We are going to look at the vulnerabilities that authentication is meant to mitigate (see table above) and explore how these authentication methods perform against each one.

VulnerabilitiesBasic authenticationToken authenticationSignature verification
Verifies sourceYesYesYes
Verifies destinationYesYesYes
Validates payloadNo: There is no built-in method of verifying that the payload is what was sent by the webhook producer.No: Tokens like JWT contain a signature that validates authentication credentials (e.g. username) but does not validate the entire webhook payload.Yes
Protects credentialsNo: Username and password encoding can be reverse engineered to expose the login credentials. You need to use secure HTTP (HTTPS) to ensure all data are encrypted.YesYes
Prevents replay attacksNo: The authenticated request can be repeated multiple times to cause undesired effects.No: For a token that is still valid (unless expired), an authenticated request can be repeated multiple times by an attacker.Yes

As seen in the table above, signature verification is the only authentication method that covers all bases. So does this mean we should discard all other authentication methods for signature verification? Not quite. Many major webhook providers like Okta, Twilio, and Stripe still support basic authentication.

Recommendation

As discussed in a previous article, webhook security methods can be applied based on the sensitivity of the information they contain or your organization’s security policies. There are simple use cases were the simplicity of basic authentication is just right. There are also cases where developers employ a composite model where we see basic authentication paired with signature verification.

However, we encourage you to have signature verification set up for maximum protection of your webhooks.

Hookdeck comes with a signature verification feature that provides plug-and-play authentication for common webhook providers like Shopify, Stripe, GitHub, etc. You can also use it to build a custom signature verification layer to authenticate your webhooks if your provider is not on the list.

Conclusion

In this article, we went through the different authentication strategies to validate the integrity of our webhooks. Webhook security is often ignored, which can lead to lots of undesired consequences. We have seen how authentication helps take care of many of the vulnerabilities that come with webhooks, which indicates that if you care about security, authenticating your webhooks should be your first step.

Happy coding!