To protect your server from unauthorised webhook events, we strongly recommend that you use Hash-based message authentication code (HMAC) signatures. After you enable HMAC signatures, each webhook event will include a signature calculated using a secret HMAC key and a payload from the webhook. By verifying this signature, you confirm that the webhook was sent by Adyen, and was not modified during transmission.
To verify HMAC signatures, you can either:
Enable HMAC signatures
To enable HMAC signed webhook events, generate a secret HMAC key in your Customer Area. The secret HMAC key is linked to a standard webhook endpoint. If you have multiple endpoints for receiving webhooks, you need to generate an HMAC key for each of them.
You also need to generate a new HMAC key when you switch from test to live.
To start receiving HMAC signed webhooks:
- Log in to your Customer Area. If you have set up webhooks for your merchant accounts, switch to the merchant account.
- Go to Developers > Webhooks.
- Select the edit icon for the Standard webhook you want to enable HMAC for.
- Under Security, select the edit icon for HMAC key.
- Select Generate.
- Copy the HMAC key using the copy icon . Store it securely in your system - you won't be able to restore it later.
- Select Apply, then Save changes.
The HMAC key will now be used to sign webhook events that we send to your server. The signature is
included in the additionalData
field:
{
"live":"false",
"notificationItems":[
{
"NotificationRequestItem":{
"additionalData":{
"hmacSignature":"+JWKfq4ynALK+FFzGgHnp1jSMQJMBJeb87dlph24sXw="
},
...
}
}
]
}
If you generate a new HMAC key, make sure that you can still accept webhooks signed with your previous HMAC key for some time, because:
- It can take some time to propagate the new key in our infrastructure.
- HMAC signatures are calculated when the webhook payload is generated, so any webhook events queued before you saved the new key are signed using your previous key.
Verify using our libraries
You can verify signatures using our:
// YOUR_HMAC_KEY from the Customer Area
String hmacKey = "YOUR_HMAC_KEY";
// Notification Request JSON
String notificationRequestJson = "NOTIFICATION_REQUEST_JSON";
HMACValidator hmacValidator = new HMACValidator();
NotificationHandler notificationHandler = new NotificationHandler();
NotificationRequest notificationRequest = notificationHandler.handleNotificationJson(notificationRequestJson);
// Handle multiple notificationRequests
List<NotificationRequestItem> notificationRequestItems = notificationRequest.getNotificationItems();
for ( NotificationRequestItem notificationRequestItem : notificationRequestItems ) {
// Handle the notification
if ( hmacValidator.validateHMAC(notificationRequestItem, hmacKey) ) {
// Process the notification based on the eventCode
String eventCode = notificationRequestItem.getEventCode();
} else {
// Non valid NotificationRequest
System.out.print("Non valid NotificationRequest");
}
}
// YOUR_HMAC_KEY from the Customer Area
$hmacKey = "YOUR_HMAC_KEY";
// Notification Request JSON
$jsonRequest = "NOTIFICATION_REQUEST_JSON";
$notificationRequest = json_decode($jsonRequest, true);
$hmac = new \Adyen\Util\HmacSignature();
// Handling multiple notificationRequests
foreach ( $notificationRequest["notificationItems"] as $notificationRequestItem ) {
$params = $notificationRequestItem["NotificationRequestItem"];
// Handle the notification
if ( $hmac->isValidNotificationHMAC($hmacKey, $params) ) {
// Process the notification based on the eventCode
$eventcode = $params['eventCode'];
print_r($eventcode);
} else {
// Non valid NotificationRequest
}
}
// YOUR_HMAC_KEY from the Customer Area
string hmacKey = "YOUR_HMAC_KEY";
// Notification Request JSON
string notificationRequestJson = "NOTIFICATION_REQUEST_JSON";
var hmacValidator = new HmacValidator();
var notificationHandler = new NotificationHandler();
var handleNotificationRequest = notificationHandler.HandleNotificationRequest(notificationRequestJson);
// Handle multiple notificationRequests
List<NotificationRequestItemContainer> notificationRequestItemContainers = handleNotificationRequest.NotificationItemContainers;
foreach ( var notificationRequestItemContainer in notificationRequestItemContainers ) {
var notificationItem = notificationRequestItemContainer.NotificationItem;
// Handle the notification
if ( hmacValidator.IsValidHmac(notificationItem, hmacKey) ) {
// Process the notification based on the eventCode
string eventCode = notificationItem.EventCode;
} else {
// Non valid NotificationRequest
}
}
const { hmacValidator } = require('@adyen/api-library');
// YOUR_HMAC_KEY from the Customer Area
const hmacKey = "YOUR_HMAC_KEY";
const validator = new hmacValidator()
// Notification Request JSON
const notificationRequest = NOTIFICATION_REQUEST_JSON;
const notificationRequestItems = notificationRequest.notificationItems
// Handling multiple notificationRequests
notificationRequestItems.forEach(function(notificationRequestItem) {
// Handle the notification
if( validator.validateHMAC(notificationRequestItem, hmacKey) ) {
// Process the notification based on the eventCode
const eventCode = notificationRequestItem.eventCode;
} else {
// Non valid NotificationRequest
console.log("Non valid NotificationRequest");
}
});
Verify using your own solution
To build your own solution for verifying HMAC signatures, follow these steps:
Step 1: Construct the payload
The values used below are from an example webhook. To test your solution, replace the values with actual values that you receive in a webhook event.
Concatenate the following values from the webhook event, in the given order:
Key | Value |
---|---|
pspReference |
7914073381342284 |
originalReference |
|
merchantAccountCode |
TestMerchant |
merchantReference |
TestPayment-1407325143704 |
value |
1130 |
currency |
EUR |
eventCode |
AUTHORISATION |
success |
true |
Assign an empty string to any fields that are empty, and use a colon (":") to delimit the values.
For the above values, with an empty originalReference
, you get:
7914073381342284::TestMerchant:TestPayment-1407325143704:1130:EUR:AUTHORISATION:true
Step 2: Calculate the HMAC signature
-
Calculate an HMAC using:
-
To get the final signature, Base64-encode the result.
Step 3: Compare signatures
If the signature that you calculated in Step 2 matches the hmacSignature
that you received, you'll know that the webhook event was sent by Adyen and was not modified during transmission.
Example
Sample HMAC key:
44782DEF547AAA06C910C43932B1EB0C71FC68D9D0C057550C48EC2ACF6BA056
Sample webhook event signed using the above HMAC key:
{
"live":"false",
"notificationItems":[
{
"NotificationRequestItem":{
"additionalData":{
"hmacSignature":"coqCmt/IZ4E3CzPvMY8zTjQVL5hYJUiBRg8UU+iCWo0="
},
"amount":{
"value":1130,
"currency":"EUR"
},
"pspReference":"7914073381342284",
"eventCode":"AUTHORISATION",
"eventDate":"2019-05-06T17:15:34.121+02:00",
"merchantAccountCode":"TestMerchant",
"operations":[
"CANCEL",
"CAPTURE",
"REFUND"
],
"merchantReference":"TestPayment-1407325143704",
"paymentMethod":"visa",
"success":"true"
}
}
]
}