Callback Authentication

Upon completion of the verification, AiPrise sends a callback (a POST request) to the set callback_url.

For events like case status update (or other actions being manually done on the dashboard), set the events_callback_url.

There are two ways to set the callback_url or events_callback_url:

  1. Set the URL at the template level. This can be set from the Dashboard > View Templates > {TemplateID}.
  2. Set the URL with each verification request using parameter callback_url or events_callback_url. (Sending the URL in this way will override the URL set at the template level using 1. above)

📘

Note

In case callback_url is set in the verification request, it will take precedence over the one set at the template level.

Authentication

How to make sure the callback response originates from AiPrise:

  • Make sure X-HMAC-SIGNATURE is present in the header
  • Generate the keyed hash of the payload using HMAC-SHA256 function and the API private key
  • Hex encode the hash
  • Compare the hex encoded hash with the X-HMAC-SIGNATURE header sent by AiPrise

How to know which callback corresponds to which request:

  • You can use the verification_session_id generated by AiPrise when the request was created.
  • You can pass an id in client_reference_id while creating the request. We pass this back in the callback.

Generating X-HMAC-SIGNATURE

  • Here are a few code examples on how to sign the request.

Example Payload

payloadAsString='{"verification_session_id": "123408f2-2bbb-415f-aafc-92212341234", "template_id": "123456-3434-2342-3453-b4218a4fb333", "client_reference_id": null, "aiprise_summary": {"tags": [], "reasons": [], "notes": [], "verification_result": "APPROVED"}, "created_at": 1668974142818}'

The result of the generated hash should be f8bf141ba610974d65f5dd603f7388474c366d1b95a13799748f92261610ba86 using code examples below with the API private key abcdef12-pqrs-abcd-pqrs-abcde0123456.

JavaScript / ECMAScript

Check troubleshooting for JS if HMAC authentication fails for Express JS

const hashVal = crypto
  .createHmac('sha256', apiKey)
  .update(Buffer.from(payloadAsString, 'utf8'))
  .digest('hex')
  .toLowerCase();

console.log(hashVal);

Python

hash_val = hmac \
        .new(
            api_key.encode('utf-8'),
            msg=bytes(payload, encoding='utf-8'),
            digestmod=hashlib.sha256
        ) \
        .hexdigest() \
        .lower()

print(hash_val)

PHP

<?php
  $hashVal = strtolower(hash_hmac('sha256', $payloadAsString, $apiKey));
  echo $hashVal;
?>

C# / .Net

var hmacsha256 = new HMACSHA256(Encoding.UTF8.GetBytes(api_key));
var hash = hmacsha256.ComputeHash(Encoding.UTF8.GetBytes(payloadAsString));
var hashVal = Convert.ToHexString(hash).ToLower();

Console.WriteLine(hashVal);

Troubleshooting in Express JS

❗️

HMAC Verification Failure

The HMAC signature relies on the precise byte sequence of the request body. Parsing can unintentionally alter this sequence by changing encoding, adjusting JSON formatting, or removing whitespaces. Even if these changes don't affect the content's meaning, they alter the byte by byte sequence, resulting in a different byte sequence. Consequently, the HMAC signature will differ, leading to a failure in Signature Verification.

Express JS has middlewares that automatically parses JSON when the Content-Type header is application/json. You can use following versions of different middlewares to parse the payloadAsString and then use it generate the HMAC.

If you're using body-parser.json() middleware with your controller, replace it with the following enhanced version:

const bodyParser = require('body-parser');

// Middleware to parse JSON and capture raw body as bytes
app.use('/<callback-url>', bodyParser.json({
  verify: (req, res, buf) => {
    req.payloadAsString = buf.toString('utf8'); // Convert buffer to string
  }
}));

If you're using express.json() middleware, replace it with the following enhanced verision:

const express = require('express');

// Middleware to parse JSON and capture raw body as a string
app.use('/<callback-url>', express.json({
  verify: (req, res, buf) => {
    req.payloadAsString = buf.toString('utf8'); // Convert buffer to string
  }
}));