Verifying Kentico Cloud webhook signatures using Express.js

Is there a way to verify the signature of webhooks using Express.js?

I've looked through the documentation on notification signatures, but I'm unsure how to integrate it with Express.js.

This question was originally posted on the official Kentico Cloud Forum and will be removed from there soon.

Answer №1

The API reference provides a sample for webhook validation in different programming languages like node.js, which can be found here.

For those using express.js, you can kickstart with the following code template:

const express = require('express');
const crypto = require('crypto');

// Initiate express
const app = express();

// Configure raw bodyparser to read webhook post
const bodyParserRaw = require('body-parser').raw({
    type: '*/*',
});

function webhookValidator (req, res, next) {
    // Extract header signature from webhook request
    const givenSignature = req.headers['x-kc-signature'];

    // Throw error if missing
    if (!givenSignature) {
        console.log('Missing signature');
        return res.status(409).json({
            error: 'Missing signature'
        });
    }

    // Create HMAC from raw request body
    let hmac = crypto.createHmac('sha256', [your-webhook-secret-key]);
    hmac.write(req.body);
    hmac.end();

    // Get base64 hash from HMAC
    let hash = hmac.read().toString('base64');

    // Check validity using timingSafeEqual
    let webhookValid = false;
    try {
        webhookValid = crypto.timingSafeEqual(Buffer.from(givenSignature, 'base64'), Buffer.from(hash, 'base64'));
    } catch (e) {
        webhookValid = false
    }

    // Return validity
    if (webhookValid) {
        return next();
    } else {
        console.log('Invalid signature');
        return res.status(409).json({
            error: 'Invalid signature'
        });
    }
}

// Create route and include bodyparser and validator
app.post('/webhook', bodyParserRaw, webhookValidator, ( req, res, next ) => {
    // If this point is reached, the HMAC is valid
    console.log('webhook is valid');
});

UPDATE

To easily validate webhook notifications and their signatures, consider using the Kontent webhook helper library. This library can be accessed as an npm package @kentico/kontent-webhook-helper, offering assistance in avoiding common hash calculation issues.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

I'm having trouble understanding why I can't redirect to my GET router after making a POST request

profile.ejs <body> <div id="box"> <h1>Greetings, <span><%= user.name %></span>!<hr> How are you feeling today?</h1> <!-- <form action="/users/logout" method=" ...

Trouble with Bootstrap popover functionality

Twitter bootstrap-2.3.2 popover is being utilized in my BackboneJs project. When I click, a function is triggered to open the popover: <li> <a class="candidPopover" href="#" id="loginUser" rel="popover"><%= candidateName %></a> & ...

Sending a POST request will generate a new file, then a subsequent GET request can be made

Seeking assistance with a seemingly simple task. I want to set up a POST request in order to send JSON data. This data will then be saved into files and made available for user download. The scenario is that I'm developing an application where users ...

Simulation of loopback session

Currently, I am utilizing loopback in conjunction with express session to store cartId. However, for the purpose of making my tests function properly, it is essential that I inject cartId into the request session. Within my remote method, I have implemen ...

The AngularJS script is throwing an error that states "ReferenceError: Invalid left-hand side in assignment

While attempting to establish a connection with a webservice, I made an attempt using AngularJS $http option. However, when testing it out, I encountered an error in the console of my Chrome browser: ReferenceError Invalid left-hand side in assignment. Des ...

Is there a way to adjust the label size for a material ui TextField component?

My TextField element is defined like this: <TextField id="standard-with-placeholder" label="First Name" className={classes.textField} margin="normal" /> It currently appears as shown in the image below: https://i.sstatic.net/aYi1a.png How ...

Verifying that the data has been successfully saved using JavaScript

When a user submits a small chunk of data via AJAX using a standard update action and a remote form, the information is sent to the action as javascript. The response is then rendered in javascript utilizing format.js. def update @message = Message.wher ...

Guide to retrieving fresh information from an API using a desktop application built on node and electron

Looking for advice on efficiently retrieving new order data from the Shopify API for a private desktop application I'm working on. Should I query the API at regular intervals while the application is active, or is there a way to implement webhooks in ...

storing information between elements

Imagine I have a requirement to include a data provider element for my users, like this: <user-data-provider user-data="{{data}}"></user-data-provider> This element would send an ajax request to retrieve the logged in user's information. ...

Trouble with NodeJS NPM

I'm encountering difficulty when trying to install npm packages. npm ERR! Windows_NT 6.3.9600 npm ERR! argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules&bso ...

Reloading nested Iframe with Selenium automation script

Currently, I am facing a challenge while working on an application that contains nested Iframes within the user interface. Some of these Iframes undergo refreshing during the test execution process. Is there any approach that allows us to simulate the refr ...

"Create dynamic tables with AngularJS using ng-repeat for column-specific rendering

I have a model called Item with the following structure: {data: String, schedule: DateTime, category: String} I want to create a report that displays the data in a table format like this: <table> <tr> <th>Time Range</th&g ...

Rails Ajax issue encountered

I previously followed a coderwall tutorial on ajax but encountered an ActionController::UnknownFormat error when attempting to open the link in a new tab (Link Name). Can anyone help me figure out what's wrong? Thanks! Additionally, clicking the link ...

Challenge with Deploying VueJs: Chrome is stuck on the previous version and not refreshing the application

Having issues with deploying my VueJs project, a web application built on the Metronic template and utilizes Vuetify components. When publishing, I use Visual Studio Code with npm run build and upload the contents of the dist folder to my server. Encoun ...

Is there a way to immobilize an object in JavaScript without resorting to Object.freeze()?

Is there a way to freeze the following object without relying on Object.freeze()? Let's find out: const obj = { a:'test', b:'Something' } ...

Trouble with JavaScript confirm's OK button functionality in Internet Explorer 11

Having trouble with the OK button functionality on a JavaScript confirm popup in IE11. For one user, clicking OK doesn't work - nothing happens. It works for most other users though. Normally, clicking OK should close the popup and trigger the event h ...

Guide on sending a JavaScript variable as a URL parameter in Django

I need to pass a radio ID to my view, but I'm struggling with how to do it using the GET method in the URL: html: <a href="{% url 'maintenance_issue_fix' %}?radio_id=checked"> <img src="{% static 'images/ma ...

Tips for concealing the cursor indefinitely in Typed JS

Is there a way to hide the cursor permanently in TypedJS so that it doesn't blink or show while typing? I've come across tutorials on hiding it after typing is complete, but not from the beginning. Any suggestions on how to achieve this? ...

Clicking on an image in a jQuery autocomplete menu will trigger a data post to an Express

My jquery autocomplete menu is functioning properly, displaying a list of books with author, title, and book image. I am now looking to enhance it by allowing users to click on the book image and then have the book title posted to an express app.post metho ...

It ceases to function when transferred to another file

I have a function written in coffeescript that goes like this: _skip_version = (currentVersion, skippedVersions) -> if (currentVersion.indexOf(skippedVersions) == -1) return false return true This function is currently located in my archive.sp ...