Skip to main content
All CollectionsIntegrateWebhooks
How to validate a webhook
How to validate a webhook

Learn how to validate a webhook using a signed secret to ensure the integrity and authenticity of the webhook payloads you receive.

Claudia avatar
Written by Claudia
Updated over 6 months ago

In this article, we will cover the steps to validate a webhook using a signed secret. This process ensures the integrity and authenticity of the webhook payloads you receive.

Step 1: Obtain Your Signed Secret

To begin, you need to obtain your signed secret. You can do this through the portal in the webhooks section after clicking on the webhook.

Alternatively you can get the signed secret using the API via a GET request. This method requires the webhook id. See this help article for more information.

Note: If you edit or update the webhook, the signed secret will change.

Step 2: Validate the Webhook

To validate the webhook, use the x-passkit-signature header that is passed along in the webhook. This header consists of two parts: a nonce value and an HMAC-SHA256 signature. The signature is generated from the nonce value and the JSON payload, which is encrypted using the signing secret.

Example: Validating the Header Using Java

Here is an example using Java to decrypt and validate the x-passkit-signature header:

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

public class Main {

/**
* Validates the x-passkit-signature header.
*
* @param signatureHeader The x-passkit-signature header value.
* @param payload The JSON payload as a string.
* @param secret Your signing secret.
* @return Returns true if the signature is valid, false otherwise.
*/
public static boolean validatePasskitSignature(String signatureHeader, String payload, String secret) {
try {
// Split the signature header to get the nonce and signature
String[] parts = signatureHeader.split(",");
String noncePart = parts[0].substring(2);
String signaturePart = parts[1].substring(4);

// Create the HMAC-SHA256 signature using the nonce and payload
String stringToSign = noncePart + "." + payload;
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
hmacSha256.init(secretKeySpec);
byte[] signatureBytes = hmacSha256.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
String expectedSignature = bytesToHex(signatureBytes);

// Compare the recreated signature with the one from the header
return expectedSignature.equals(signaturePart);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}

/**
* Converts a byte array to a hex string.
*
* @param bytes The byte array to convert.
* @return The hex string representation of the byte array.
*/
private static String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}

public static void main(String[] args) {
String signatureHeader = "your x-passkit-signature";
String payload = "your json payload";
String secret = "your secret";

boolean isValid = validatePasskitSignature(signatureHeader, payload, secret);
System.out.println("Signature is valid: " + isValid);
}
}

Explanation:

  1. Splitting the Signature Header: The x-passkit-signature header is split to extract the nonce and the signature.

  2. Creating the Signature: An HMAC-SHA256 signature is created using the nonce and the JSON payload.

  3. Comparing Signatures: The recreated signature is compared with the one from the header to validate the webhook.

This example provides a robust method to ensure that the webhook payloads you receive are from a trusted source and have not been tampered with.

If you run into any errors with validation, please check that the payload is formatted correctly. Proper formatting of the JSON payload is crucial for the validation process to work correctly.

Did this answer your question?