Skip to content
Last updated

Webhook signature validation

Generate signature and set authentication

This step must be completed to setup webhooks on your app

Before creating a webhook, you need to generate a signature digest key. This key will be used to validate the HMAC signature in each incoming webhook request, confirming the request’s authenticity and integrity.

curl -X PUT "https://api.staging.adfin.com/api/apps/{client_id}/webhooks/digest"

Explanation

  1. URL: Replace {client_id} with the unique client_id of your app.
  2. Response: This request will return a secret key that should be securely stored and used to validate incoming webhook signatures. Make sure this key is handled and stored with strict security measures.

You need to set up an authentication method for the webhook to ensure that only requests with valid credentials are accepted by your platform. Use any of the following:

  • Basic Auth
  • API Key
curl -X PUT "https://api.staging.adfin.com/api/apps/{client_id}/webhooks/auth" \
-H "Content-Type: application/json" \
-d '{
  "basicAuthentication": {
    "username": "{{exampleValue}}",
    "password": "{{exampleValue}}"
  }
}'

Verify incoming webhook requests (optional)

With the signature digest key and authentication method set up, you can now verify incoming webhook requests.


Webhook request headers

Every webhook request from Adfin includes these headers:

  • adfin-webhook-signature: The HMAC signature of the payload.
  • adfin-webhook-signature-timestamp: The timestamp of when the request was generated.

Example Headers:

adfin-webhook-signature: H63TRZj13EwxnpRFg454yLH92bm3jZyv31=
adfin-webhook-signature-timestamp: 2024-10-01T09:01:35Z

Signature Verification Process

To verify the webhook, follow these steps:

  1. Concatenate: Combine the request payload (body) and the signature timestamp (adfin-webhook-signature-timestamp).
  2. Generate HMAC: Use the signature digest key generated in Step 1 to create an HMAC SHA-256 hash of the concatenated data.
  3. Compare: Verify that the HMAC hash matches the adfin-webhook-signature header.

Java example for signature verification

Here’s a Java example to verify the signature:

private String generateVerificationSignature(String data, String key) {

		final String algorithm = "HmacSHA256";

		if (data == null || key == null) {
			throw new IllegalArgumentException("data and secretKey must not be null");
		}

		try {
			Mac hmacSHA256 = Mac.getInstance(algorithm);

			SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), algorithm);
			hmacSHA256.init(secretKeySpec);
			byte[] dataBytes = hmacSHA256.doFinal(data.getBytes(StandardCharsets.UTF_8));
			return new String(Base64.getEncoder().encode(dataBytes));
		} catch (NoSuchAlgorithmException | InvalidKeyException e) {
			throw new RuntimeException("Signature verification failed", e);
		}
	}

private boolean isSignatureValid(String signatureTimestampHeader, String signatureHeader, String eventPayload, String secretKey) {

		String SEPARATOR = "||";
		String data = signatureTimestampHeader + SEPARATOR + eventPayload;
		String verificationSignature = generateVerificationSignature(data, secretKey);
		return signatureHeader.equals(verificationSignature);
	}

Handling authentication in webhook requests

Based on the configured authentication method:

  • Basic Authentication: Check for Authorization: Basic base64(username:password).
  • API Key Authentication: Verify that the request includes the correct header and value pair (e.g., x-api-key: testApiKey).

Respond to the webhook

After validating the signature and authentication, respond to the webhook with a 2XX status code if successful. If validation fails, respond with an appropriate error code (e.g., 400 Bad Request or 401 Unauthorized).


Security best practices

  • Securely Store Credentials: Ensure both the signature digest key and authentication credentials are stored securely and rotated periodically.
  • Log Events: Log webhook validation attempts and responses for audit and troubleshooting.
  • Rate Limiting: Apply rate limiting to your webhook endpoint to prevent abuse.