DEV Community

Cover image for A Developer’s Guide to HMAC Validation for Adyen Webhooks
Beppe Catanese for Adyen

Posted on

A Developer’s Guide to HMAC Validation for Adyen Webhooks

Introduction

When it comes to payments, security isn’t optional — it’s essential. If you’re integrating with Adyen, ensuring the incoming webhooks’ authenticity and integrity is very important. That’s where Hash-based Message Authentication Code (HMAC) plays a critical role in securing your Adyen integration.

Image description

Implementing, testing, and troubleshooting HMAC validation can be challenging. This guide explains how HMAC validation works, highlights the challenges, and provides tools and best practices for secure and reliable implementation.

HMAC at Adyen

All Adyen webhooks use HMAC to ensure the integrity and authenticity of the payloads delivered to your integrations. The HMAC key should be enabled when setting up a new webhook (either in the Customer Area Webhook page or using the Management API).

Adyen will use the HMAC key to sign the payload by creating an HMAC signature. You must validate the HMAC signature, delivered with the webhook, using the same HMAC key.

Adyen webhooks fall into two main categories, each with its approach to HMAC implementation. Let’s explore the two scenarios.

1. Payments Webhooks

For payments-related webhooks, the calculation of the signature involves using a subset of fields, and it’s embedded directly within the JSON payload under the additionalData object:

{
   "live":"false",
   "notificationItems":[
      {
         "NotificationRequestItem":{
            "additionalData":{
               "hmacSignature":"+JWKfq4ynALK+FFzGgHnp1jSMQJMBJeb87dlph24sXw="
            },
          ...
         }
      }
   ]
}
Enter fullscreen mode Exit fullscreen mode

2. Other Webhooks (Adyen for Platforms, Management)

For non-payment webhooks, the signature is calculated using the entire JSON payload. Instead of being included in the payload itself, the signature is provided in the HTTP Header hmacSignature:

content-length: 1614
content-type: application/json
hmacsignature: SMQZFOq3oIdugmf97u9TB+5256jjXgUX3MRjK+RlGNQ=
Enter fullscreen mode Exit fullscreen mode

Implementing HMAC Validation

Developers have two options for implementing HMAC validation: creating their validation function or using the Adyen’s open-source libraries.

Custom Implementation

If you choose to implement your own HMAC validation, you’ll need to follow Adyen’s documentation:

Implementing a custom HMAC validation is not trivial — it requires handling the correct fields in the exact order and matching the encryption algorithm. Instead, use Adyen’s libraries to simplify the process, reducing both effort and risks.

Using Adyen Libraries (Recommended)

Use the Adyen open-source libraries, which provide built-in functions for calculating and validating HMAC signatures. The libraries are thoroughly tested, regularly updated, and available in multiple programming languages (Node.js, PHP, Java, .NET, etc.).

String payload = "....";

// obtain signature
String hmacsignature = headers.get("hmacsignature");
if (hmacsignature == null || hmacsignature.isBlank()) {
   log.warn("HMAC Signature not found");
   throw new RuntimeException("HMAC Signature not found");
}

// perform HMAC validation 
if (!hmacValidator.validateHMAC(payload, hmacsignature, "MY_HMAC_KEY")) {
  throw new RuntimeException("Invalid HMAC signature");
}
Enter fullscreen mode Exit fullscreen mode

Example of Java snippet to validate the HMAC signature

Known Issues and Challenges

HMAC validation errors are, unfortunately, common and challenging to troubleshoot. Several aspects contribute to this complexity:

  • Propagation delay when updating the HMAC key

  • Using the correct HMAC key

  • Unexpected modification of the webhook payload

HMAC Key Update Propagation Delay

When users update (regenerate) the HMAC key associated with a webhook, there’s a delay (up to 10 minutes) before the new HMAC key is fully propagated and used by all webhook components. During this transition period, both the previous and new HMAC keys remain valid.

This delay can lead to validation failures if the implementation isn’t prepared to handle the transition period, especially if you immediately discard the old key when generating a new one.

The best practice here is to maintain both keys temporarily during the transition window.

Using the Correct HMAC Key

One of the most common issues occurs when developers use the HMAC key from a different webhook configuration. With multiple webhooks in use, especially across development, testing, and production environments, it’s easy to mix up which key belongs to which webhook.

Key Check Value (KCV) Verification

The Key Check Value (KCV) is a short hex value derived from the HMAC key that serves as a fingerprint to verify the key (without revealing it).

The KCV is found on the Webhook Configuration page in the Adyen Customer Area (CA). When troubleshooting, always compare the KCV of the HMAC key you’re using with the one displayed in the CA to confirm you’re working with the correct key.

Image description
Webhook Configuration page showing the KCV

You can validate the KCV by implementing the following steps:

1. Calculate an 8-digit zero hash (“00000000”) using your HMAC key with the HMAC-SHA256 algorithm

2. Take the last 3 bytes of the resulting hash and convert it to an uppercase hex string

3. Compare this value with the KCV shown in the Customer Area

Adyen’s libraries simplify this process by including scripts to calculate the KCV, making it easy to verify that you’re using the correct HMAC key.

Unexpected Modifications of the Webhook Payload

A common but often overlooked cause of HMAC validation failures is unintentional modification of the webhook payload.

Adyen webhooks deliver information relevant to the customer’s integration (such as references, amounts, etc.) without trimming or encoding data. However, application frameworks and third-party libraries might alter incoming requests in various ways:

  • Trimming whitespaces

  • Converting line endings

  • Normalizing JSON structures

  • Decoding URL-encoded characters

Check if any infrastructure (web servers, API gateways, proxies) between Adyen and your application could be altering the payload of the incoming HTTP request.

Before any framework processing, capture the raw webhook body and use the proper comparison (byte or string comparison rather than object matching). During your testing, it’s a good practice to test payloads containing special characters and whitespaces to ensure proper handling.

HMAC Validation Troubleshooting

When faced with HMAC validation failures, there are several approaches to troubleshoot and resolve the issue.

Test in Customer Area (CA)

The Adyen Customer Area provides a built-in feature to test your webhook configuration:

  1. Go to Developers -> Webhooks -> Edit webhook

  2. Click on “Test Configuration”

  3. Choose an “Event” type from the dropdown

  4. Click “Test” to send the webhook to your endpoint

  5. Verify the HTTP response is successful by returning a 2xx response status code

This page allows you to edit the webhook payload as needed (for example, changing a reference, amount, or other fields). The HMAC signature will be automatically recalculated and delivered with the new request.

When to use Customer Area Testing

Send webhooks from the Customer Area to verify the end-to-end flow: Adyen sends the webhook, your integration receives the event, and your implementation validates the HMAC signature. This method is ideal for confirming that the entire flow works correctly.

Test with Postman Collection

Our AdyenDev Postman space includes a Postman collection designed explicitly for webhook testing:

1. Fork the Adyen Postman collection to your private workspace

2. Define collection variables, including your HMAC key

3. Update the webhook payload as needed

4. Send the request to your application’s webhook endpoint

The Adyen Webhooks Postman collection contains several sample payloads you can use or modify to simulate webhook events. It automatically calculates the HMAC signature when sending the request.

When to use Postman testing

Use Postman to test webhooks in isolation. This is ideal for validating your implementation without involving the Adyen backend and focusing on how your integration handles webhook events independently.

Test with Adyen Library Scripts

Adyen libraries include built-in methods to calculate the HMAC signature using your HMAC key and JSON payload. Check out the code from GitHub or open the GitHub repository in Codespaces (browser-based development environment), and follow the instructions specific to the library

For example, if you are using the Node API library and need to troubleshoot an issue with the HMAC validation, you can calculate the HMAC signature in 2 simple steps.

First go to the folder that includes the scripts, and install the necessary dependencies:

// go to dir and setup
cd tools/hmac
npm install
Enter fullscreen mode Exit fullscreen mode

Calculate the HMAC signature, passing the JSON payload and the HMAC key:

// run script passing the HMAC key and the JSON file with the payload
node calculateHmacPayments.js 11223344D785FBAE710E7F943F307971BB61B21281C98C9129B3D4018A57B2EB payload.json
Enter fullscreen mode Exit fullscreen mode

⚠️ Important: When reusing a JSON payload, ensure it doesn’t get modified, formatted, or “prettified,” as this would alter the payload and result in a different signature.

Run in Codespaces

You can use effortlessly GitHub Codespaces to run these scripts directly from your browser:

1. Open the GitHub repository for your Adyen library

2. Start a Codespaces workspace

3. In the terminal, navigate to the appropriate directory and run the scripts

@user ➜ cd /tools/hmac
@user ➜ npm install
up to date, audited 8 packages in 477ms

@user ➜ npm list @adyen/api-library
[email protected] /workspaces/adyen-node-api-library/tools/hmac
└── @adyen/[email protected]

@user ➜ node calculateHmacPayments.js 11223344D785FBAE710E7F943F307971BB61B21281C98C9129B3D4018A57B2EB payload.json

Calculating HMAC signature with payload from 'payload.json'
HMAC signature: qHNSvxCCix79xgBdWemxf0rcNMWoLrMK/4IgMnkOsWI=
Enter fullscreen mode Exit fullscreen mode

When to use Library Built-in Scripts

Use these scripts to troubleshoot HMAC validation failures in applications using the Adyen libraries: verify the expected HMAC signature using your HMAC key and payload.

⚠️ Important: signatures not matching

If your application calculates a different HMAC signature than these scripts, potential issues might include:

  • Using an outdated version of the library

  • Using the wrong HMAC key

  • Working with a modified payload (check for spaces, formatting, and special characters)

Image description

Key takeaways for successful HMAC implementation

This article explains HMAC validation, common challenges, and how to troubleshoot issues effectively:

  • Use Adyen’s open-source libraries to simplify HMAC validation.

  • Manage HMAC key updates to avoid discarding old keys too early.

  • Avoid payload modifications to maintain signature integrity.

  • Leverage Adyen’s testing and troubleshooting tools.

Follow our guidelines and best practices to securely process Adyen webhooks and deliver a seamless payment experience to your shoppers 💚

Top comments (0)