Signature Webhooks

A webhook is a user-defined callback over HTTP. You can use eID Easy webhooks to get notified of the signature lifecycle events. For example, let's say that you wish to perform some actions in your application e.g. download the signed document after it has been signed. To achieve that, you could configure a URL to which eID Easy will send a POST request every time a document has been signed. This means you do not necessarily need to rely on polling to detect changes.

Document signed webhook

This webhook gets triggered after a document has been signed.

It will send a POST request with a 30-second timeout. If you respond to the webhook with HTTP status code 4xx or 5xx, then eID Easy server will try to call the webhook again in 5 minutes and then again in 60 minutes.

Example of the POST body:

{
  "doc_id": "vbs3456kvT6Jl8k1ORV62YHfgtyhse03y01CRWHV",
  "signer_id": "PNOEE-1234567889",
  "notification_state": null,
  "template_id": "234fwef",
  "signing_time": 1643026385078,
  "signing_method": "smart-id-signature",
  "signature_level": "qualified",
  "signer_data": {
    "name": "TESTMAR TESTSSSSSSÖN",
    "id_code": "123456789",
    "country": "EE"
  }
}

To register this webhook:

  1. go to https://id.eideasy.com/adminopen in new window
  2. scroll to the section "Notification hooks"
  3. fill in the field "Signature notification URL" with the url to which you wish to receive the webhook requests

Custom signature image webhook

This webhook is useful if you wish to generate custom signature images.

It gets triggered before the default signature image is created during the pdf signing process and will send a POST request with a 5-second timeout.

Example of the POST body:

{
  "signer_name": "Tero Testi Äyrämö",
  "signer_idcode": null,
  "signer_country": null,
  "signer_birthdate": "1970-01-01",
  "signer_phone": null,
  "signer_email": null,
  "signing_method": "fi-ftn-advanced-signature",
  "signing_time": 1643028548933,
  "doc_id": "WDQQnj9ZqYzQy62Zi7j8934yhf0efry3djow"
}

If you respond to this webhook with your own base64 encoded image, then the image you provided will be used instead of the default signature image:

{
  "base64_encoded_image": "yourBase64EncodedImage",
  "image_width": 600,
  "image_height": 147
}

The default signature image looks like this: eID Easy signature image

To register this webhook:

  1. go to https://id.eideasy.com/adminopen in new window
  2. scroll to the section "Whitelabel"
  3. fill in the field "Custom visual signature pdf webhook" with the url to which you wish to receive the webhook requests

Custom CAdES digest webhook

This webhook gets triggered in case of CAdES signatures right after eID Easy has received the end-user's signing certificate.

It can be handy if you are using API Based Flow With File Hashes for PDF and wish to add some data to your PDF, based on the signer's identity. For example, you might wish to embed a custom signature image with the signer's name and id to your PDF. To achieve that:

  1. You can listen for this webhook.
  2. This webhook gets triggered when eID Easy has received the end-user's signing certificate. Webhook's body will contain the signer data.

Example of the webhook's POST body:

{
  "signer_name": "QUALIFIED OK1 TESTNUMBER",
  "signer_idcode": "PNOEE-30303039914",
  "signing_method": "smart-id-signature",
  "signing_time": 1644404588706,
  "doc_id": "cTzZ7kjlngFbUdvFFl2GDtgO944npiIHaue0NiEP"
}
  1. You can now use this data to create a signature image, embed it to your PDF and calculate the final digest to be signed.
  2. You then respond to the webhook with hex encoded digest:
{
  "digest": "796F7572446967657374"
}
  1. eID Easy will then use this digest to generate the final CAdES signature.

To register this webhook:

  1. go to https://id.eideasy.com/adminopen in new window
  2. scroll to the section "Whitelabel"
  3. fill in the field "Custom CAdES digest webhook" with the url to which you wish to receive the webhook requests

Secure your webhook

Listening to a webhook involves making a URL (the webhook endpoint) accessible on the internet. This presents a security concern as anyone can send requests to this endpoint. It is therefore important that you verify that the request is coming from eID Easy and not from a malicious third party before you respond to it.

Each webhook request contains a base64-encoded x-eideasy-hmac-sha256 header, which is generated by signing the request payload with the client secret. You should always verify this signature before responding to the webhook.

  1. Compute the HMAC according to the following example:
<?php

function verifyWebhook($data, $hmacFromHeader, $clientSecret): bool
{
    $calculatedHmac = base64_encode(hash_hmac('sha256', $data, $clientSecret, true));
    return hash_equals($calculatedHmac, $hmacFromHeader);
}

$clientSecret = 'your-client-secret';
$hmacFromHeader = $_SERVER['HTTP_X_EIDEASY_HMAC_SHA256'];
$data = file_get_contents('php://input');
$verified = verifyWebhook($data, $hmacFromHeader, $clientSecret);

if ($verified) {
    echo 'success';
} else {
    echo 'invalid';
}
const express = require('express');
const app = express();
const crypto = require('crypto');

const port = 3000;
const clientSecret = 'your-client-secret';
app.use(express.raw({type: 'application/json'}));

app.post('/webhook', async (request, response) => {
  const signatureFromHeader = request.headers['x-eideasy-hmac-sha256'];
  const requestBody = request.body.toString();

  if (verifyWebhook(signatureFromHeader, requestBody, clientSecret)) {
    console.log('success');
    response.sendStatus(200);
  } else {
    throw new Error('Webhook signature is not valid');
  }
});

function verifyWebhook(signatureFromHeader, requestBody, clientSecret) {
  const result = crypto
    .createHmac('sha256', clientSecret)
    .update(requestBody)
    .digest('base64');

  return result === signatureFromHeader;
}

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
});
2. Compare the computed HMAC to the value in the x-eideasy-hmac-sha256 header. If both match, then the webhook was sent from eID Easy.

Note: your client secret is the same one that you use to make API calls to eID Easy. If you do not have the API credentials yet follow this guide.

Last Updated: