RPM Webhooks

In RPM 12 we will be introducing webhooks, which allow third party systems to get notified when certain events happen in a process in RPM:whenever the event occurs an HTTP POST request is sent to a specific URL with details of what happened and which form was affected.

Setup

When setting up a new webhook you need to provide:

  1. Name – identify the webhook
  2. Process – identify the associated process
  3. Url – the url to request when the event happens
  4. Event – the event to track. The events available are:
    • form.start – when a form is created on the associated process
    • form.edit – when a form is edited on the associated process (including archive/unarchive)
    • form.trash – when a form on the associated process is sent to the trash
    • form.restore – when a form on the associated process is restored from the trash
    • action.add – when an action is added to a form (Since RPM18)
    • action.edit – when an action is edited on a form (Since RPM18)
  5. Secret – secret key used to generate a checksum to allow the receiving system to confirm the request is indeed from RPM (do not publish anywhere, should only be known by RPM and the receiving system)

webhook

Receiving the HTTP Request

The receiving system will receive an HTTP Request using POST. The following headers are sent with the request:

  • Content-Type – <string> the type of the POST data content (always application/json)
  • X-RPM-Instance – <string> The instance name for the sending RPM instance
  • X-RPM-InstanceID – <int> The instance ID for the sending RPM instance
  • X-RPM-Subscriber – <int> The ID of the subscriber where the event happened
  • X-RPM-Signature – <string> checksum signature to allow receiving system to validate the request
  • User-Agent – RPM-Webhook
  • Host – IP address of the RPM instance that generated the request
  • Content-Length – Length of POST data

Note: RFC-2616 states that headers are case-insensitive so it is recommended to match headers in that way.

Here’s an example request received:

Content-Type: application/json
X-RPM-Instance: Cube11
X-RPM-InstanceID: 2001
X-RPM-Subscriber: 1071
X-RPM-Signature: 930c0cacf3866d3fa71ed5c5dbac39fe5330b4e3908039e0d689dcf8a0ffb780
User-Agent: RPM-Webhook
Host: 192.168.0.37:81
Content-Length: 124
Expect: 100-continue
Connection: Keep-Alive


{"ObjectID":67346,"ObjectType":520,"ParentID":2011,"ParentType":510,"EventName":"form.edit","RequestID":416,"StatusID":5415}

Validating the request

To prevent forged requests or DDoS attacks, RPM sends the X-RPM-Signature header which is the result of encrypting the request body via an HMAC encryption using SHA256 (using the Secret as the crypto key).

The receiving system should repeat the same HMAC encryption process using the same shared secret key to confirm the request is valid. If the X-RPM-Signature header is missing or the checksum does not match then the system can consider the requesting IP address for blacklisting.

Examples

PHP

$headers = [];
// make headers lowercase
foreach (getallheaders() as $name => $value) {
	$name = strtolower($name);
	$headers[$name] = $value;
}
$body    = file_get_contents('php://input');
$secret  = 'valar morghulis'; // your own secret
$hashed  = hash_hmac('sha256', $body, $secret);

if ($hashed === $headers['x-rpm-signature']) {
	echo "This request is legit";
} else {
	die("You shall not pass");
}

NodeJS

    var crypto = require('crypto');
    var secret = 'Alles dreht sich!'; // Your own secret

    function getSignature(data, secret) {
        var hmac = crypto.createHmac('sha256', secret);
        hmac.update(typeof data === 'object' ? JSON.stringify(data) : '' + data);
        return hmac.digest('hex');
    }

    function validateSignature(signRecieved, data, secret) {
        var signCalculated = getSignature(data, secret);
        if (signCalculated !== signRecieved) {
            throw new Error(util.format('Wrong signature. Calculated: %s, recieved: %s', signCalculated, signRecieved));
        }
    }

    validateSignature($headers['x-rpm-signature'], request.body, secret);

Webhooks and API requests

RPM’s web API allows applications to add, edit, archive, unarchive and trash forms, as well as adding and editing actions via API. By default, these request will not trigger webhooks.

To enable API users to trigger webhooks, a new WebhookEvaluate parameter has been added to those requests.

Be conscious that you could produce cyclic requests if not careful when making WebhookEvaluate true.

%d bloggers like this: