Building a Valid Webhook Signature

Verifying the integrity and authenticity of webhook events is important for maintaining secure and reliable communications between Payiano and your server. A valid webhook signature ensures that the payload received has not been tampered with and is indeed from Payiano. This process involves several steps that transform the payload into a format that can be securely signed and verified, providing a robust mechanism to protect against unauthorized or altered data.

The process of generating a webhook signature includes flattening nested objects and arrays, sorting the keys alphabetically, excluding null values and removing new lines from strings, encoding the values, and finally using HMAC to create the signature with a provided secret. By following these detailed steps, you can ensure that each webhook event's payload is handled consistently and securely, allowing your application to process the data with confidence in its authenticity.

Steps to Build a Valid Webhook Signature

Please follow these steps to build a valid webhook signature manually. Regardless of the programming language or tool you use, these simple steps will guide you on how to build a valid webhook signature using your signature secret. You can test with the following payload that covers almost all scenarios you might face with all the webhook events payload.

Example Payload:
1
{
2
"webhook_event": {
3 "id": "01j3521znn3b6wderr4vbyq18n", 4 "type": "company.created", 5 "version": "v1", 6 "fired_at": "1722572118554" 7 }, 8
"webhook_event_attempt": {
9 "id": "01j354j6nkwh3mdvhs6dsmswt8", 10 "sent_at": "1722572118554" 11 }, 12
"details": {
13
"data": {
14
"company": {
15 "name": "Pyngy URL Shortenr", 16 "avatar": null, 17 "is_active": true, 18 "is_approved": false, 19 "employees_count": 0, 20
"owners": [
21
{
22 "name": "Amgad Yassen", 23 "position": "CEO", 24 "percentage": 51.5 25 }, 26
{
27 "name": "Kamal Allam", 28 "position": "CEO", 29 "percentage": 48.5 30 } 31 ], 32 "description": "A leading company providing solutions for converting lengthy URLs into short ones & simplifying online sharing!", 33
"social_urls": {
34 "facebook_url": "https://facebook.com/pyngy", 35 "linked_in_url": null 36 } 37 } 38 } 39 } 40}

1. Flatten the Payload

Flattening an object or an array involves transforming nested objects or arrays into a single level, where each key represents the path to the corresponding value in the original structure. Given the original nested JSON payload, flattening it means converting each nested key into a single key string that represents the hierarchy.

Flattened Payload:
1
{
2 "webhook_event.id": "01j3521znn3b6wderr4vbyq18n", 3 "webhook_event.type": "company.created", 4 "webhook_event.version": "v1", 5 "webhook_event.fired_at": "1722572118554", 6 "webhook_event_attempt.id": "01j354j6nkwh3mdvhs6dsmswt8", 7 "webhook_event_attempt.sent_at": "1722572118554", 8 "details.data.company.name": "Pyngy URL Shortenr", 9 "details.data.company.avatar": null, 10 "details.data.company.is_active": true, 11 "details.data.company.is_approved": false, 12 "details.data.company.employees_count": 0, 13 "details.data.company.owners.0.name": "Amgad Yassen", 14 "details.data.company.owners.0.position": "CEO", 15 "details.data.company.owners.0.percentage": 51.5, 16 "details.data.company.owners.1.name": "Kamal Allam", 17 "details.data.company.owners.1.position": "CEO", 18 "details.data.company.owners.1.percentage": 48.5, 19 "details.data.company.description": "A leading company providing solutions for converting lengthy URLs into short ones & simplifying online sharing!", 20 "details.data.company.social_urls.facebook_url": "https://facebook.com/pyngy", 21 "details.data.company.social_urls.linked_in_url": null 22}

2. Clean the Payload

When generating HMAC signatures, it's important to ensure the data is consistent across different programming languages and systems. Differences in how null values, spaces and new lines in strings are handled can cause errors. Cleaning the data helps prevent these issues by standardizing the format. We remove any null values, spaces and any new lines from strings to build the signature.

Cleaned Payload:
1
{
2 "webhook_event.id": "01j3521znn3b6wderr4vbyq18n", 3 "webhook_event.type": "company.created", 4 "webhook_event.version": "v1", 5 "webhook_event.fired_at": "1722572118554", 6 "webhook_event_attempt.id": "01j354j6nkwh3mdvhs6dsmswt8", 7 "webhook_event_attempt.sent_at": "1722572118554", 8 "details.data.company.name": "PyngyURLShortenr", 9 "details.data.company.is_active": true, 10 "details.data.company.is_approved": false, 11 "details.data.company.employees_count": 0, 12 "details.data.company.owners.0.name": "AmgadYassen", 13 "details.data.company.owners.0.position": "CEO", 14 "details.data.company.owners.0.percentage": 51.5, 15 "details.data.company.owners.1.name": "KamalAllam", 16 "details.data.company.owners.1.position": "CEO", 17 "details.data.company.owners.1.percentage": 48.5, 18 "details.data.company.description": "AleadingcompanyprovidingsolutionsforconvertinglengthyURLsintoshortones&simplifyingonlinesharing!", 19 "details.data.company.social_urls.facebook_url": "https://facebook.com/pyngy" 20}

3. Sorting the Payload Alphabetically

Different systems can arrange JSON objects in different orders, which can cause inconsistencies. Sorting the keys alphabetically makes sure the data is always in the same order, no matter where it's used. This helps ensure that the HMAC signature is consistent across different systems and programming languages. By sorting the keys, we avoid any issues caused by keys being in different orders.

Sorted Payload:
1
{
2 "details.data.company.description": "AleadingcompanyprovidingsolutionsforconvertinglengthyURLsintoshortones&simplifyingonlinesharing!", 3 "details.data.company.employees_count": 0, 4 "details.data.company.is_active": true, 5 "details.data.company.is_approved": false, 6 "details.data.company.name": "PyngyURLShortenr", 7 "details.data.company.owners.0.name": "AmgadYassen", 8 "details.data.company.owners.0.percentage": 51.5, 9 "details.data.company.owners.0.position": "CEO", 10 "details.data.company.owners.1.name": "KamalAllam", 11 "details.data.company.owners.1.percentage": 48.5, 12 "details.data.company.owners.1.position": "CEO", 13 "details.data.company.social_urls.facebook_url": "https://facebook.com/pyngy", 14 "webhook_event.fired_at": "1722572118554", 15 "webhook_event.id": "01j3521znn3b6wderr4vbyq18n", 16 "webhook_event.type": "company.created", 17 "webhook_event.version": "v1", 18 "webhook_event_attempt.id": "01j354j6nkwh3mdvhs6dsmswt8", 19 "webhook_event_attempt.sent_at": "1722572118554" 20}

4. Joining Key-Value Pairs

To create a consistent and reliable string for signature purposes, each key is combined with its corresponding value using (=) in a simple array.

Simplified Payload:
1
[
2 "details.data.company.description=AleadingcompanyprovidingsolutionsforconvertinglengthyURLsintoshortones&simplifyingonlinesharing!", 3 "details.data.company.employees_count=0", 4 "details.data.company.is_active=true", 5 "details.data.company.is_approved=false", 6 "details.data.company.name=PyngyURLShortenr", 7 "details.data.company.owners.0.name=AmgadYassen", 8 "details.data.company.owners.0.percentage=51.5", 9 "details.data.company.owners.0.position=CEO", 10 "details.data.company.owners.1.name=KamalAllam", 11 "details.data.company.owners.1.percentage=48.5", 12 "details.data.company.owners.1.position=CEO", 13 "details.data.company.social_urls.facebook_url=https://facebook.com/pyngy", 14 "webhook_event.fired_at=1722572118554", 15 "webhook_event.id=01j3521znn3b6wderr4vbyq18n", 16 "webhook_event.type=company.created", 17 "webhook_event.version=v1", 18 "webhook_event_attempt.id=01j354j6nkwh3mdvhs6dsmswt8", 19 "webhook_event_attempt.sent_at=1722572118554" 20]

5. Building the Signature String

To ensure a consistent and reliable HMAC signature, we need to create a single string from the simplified key-value pairs. This involves joining the simplified key-value pairs with &.

Signature:
details.data.company.description=AleadingcompanyprovidingsolutionsforconvertinglengthyURLsintoshortones&simplifyingonlinesharing!&details.data.company.employees_count=0&details.data.company.is_active=true&details.data.company.is_approved=false&details.data.company.name=PyngyURLShortenr&details.data.company.owners.0.name=AmgadYassen&details.data.company.owners.0.percentage=51.5&details.data.company.owners.0.position=CEO&details.data.company.owners.1.name=KamalAllam&details.data.company.owners.1.percentage=48.5&details.data.company.owners.1.position=CEO&details.data.company.social_urls.facebook_url=https://facebook.com/pyngy&webhook_event.fired_at=1722572118554&webhook_event.id=01j3521znn3b6wderr4vbyq18n&webhook_event.type=company.created&webhook_event.version=v1&webhook_event_attempt.id=01j354j6nkwh3mdvhs6dsmswt8&webhook_event_attempt.sent_at=1722572118554

6. Computing and Verifying the Signature

Once the signature string is built, you need to compute the HMAC signature using the SHA256 algorithm. This computed signature should then be compared to the signature provided with the webhook request in the X-Payiano-Webhook-Signature header.

  • Use the provided secret key and the SHA256 algorithm to compute the HMAC signature from the signature string.
  • Compare the computed signature with the signature received in the X-Payiano-Webhook-Signature header of the webhook request.
  • If both signatures match, the webhook payload is confirmed to be valid and untampered. If they do not match, the webhook request may have been altered and should not be trusted.
Signature secret: OWlPF9plag9KEtYvw3EM+7UDrgXb84xjZPR2TvzJM1I=
Computed signature: 7159d656803a7136be897193dd70a48ca757786d0fe3531f33a48dc17d995725

Example Code Snippets

We have provided example code snippets to assist developers in manually creating valid signatures and verifying them across different programming languages. These snippets ensure that the process is consistent and secure. You can find these examples on our Github repository:

If you require code snippets in additional programming languages, need further assistance with the provided examples, or have any other inquiries, our team is here to help. Please don't hesitate to contact us. We are committed to ensuring your integration process is smooth and successful.