Signature Verification

Learn how to ensure the webhook payload received is sent by Plural.

Webhook signature verification is a critical security measure to protect your system from unauthorized access, data tampering, and other potential threats.

We include a signature that you can use to verify that the webhook payload you receive is legitimate and sent by us. The signature is sent against the webhook-signature parameter in the header in all the webhook events.

Verify Signature

Follow the below steps to verify the webhook signature.

  1. All the webhook events sent from Plural include these three header information along with the body which are used for verification.
    1. webhook-id: A unique identifier of the webhook event. This remains the same when the webhook is resent and this can be ignored.
    2. webhook-timestamp: The unix timestamp (in seconds) when the webhook event was triggered.
    3. webhook-signature: Base64 encoded webhook signature.
  2. Use the webhook_id, webhook_timestamp, body, and secret_key to generate a signature.

πŸ“˜

Note

  • Where body is the raw response body of a webhook event.
  • secret_key: You can find your secret key under settings on the Plural dashboard.
  1. You can use the sample code below to generate a signature and encode it to Base64.
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class Main {
  public static void main(String[] args) {
    String webhook_id = "<webhook_id>"; // Replace with actual webhook_id
    String webhook_timestamp = "<webhook_timestamp>"; // Replace with actual webhook_timestamp
    String body = "<body>"; // Replace with actual body

    String signedContent = webhook_id + "." + webhook_timestamp + "." + body;
    String secret = "<secret_key>"; // Replace with actual secret key

    // Need to base64 decode the secret
    byte[] secretBytes = Base64.getDecoder().decode(secret);
    String signature = "";

    try {
      Mac mac = Mac.getInstance("HmacSHA256");
      SecretKeySpec secretKeySpec = new SecretKeySpec(secretBytes, "HmacSHA256");
      mac.init(secretKeySpec);
      byte[] hmacBytes = mac.doFinal(signedContent.getBytes(StandardCharsets.UTF_8));
      signature = Base64.getEncoder().encodeToString(hmacBytes);
    } catch (Exception e) {
      e.printStackTrace();
    }

    System.out.println(signature);
  }
}

Refer to our signature verification recipe to learn more.

  1. Next, compare the generated signature with the header webhook_signature.
  2. To compare the signatures it's recommended to use a constant-time string comparison method in order to prevent timing attacks.
  3. Additionally, you can also compare the webhook timestamp against your system timestamp to ensure it's within your acceptable time range.

πŸ“˜

Note:

By comparing the generated signature with the one provided, you can verify that the webhook was sent by Plural and that the data remained intact during transmission.