Get your copy[New whitepaper] Why E-commerce Customer Experiences Matter (And How to Improve Them)
Petil shape

How to verify and process webhook notifications in Next.js

Processing webhook notifications is now possible directly within your Next.js website implementation. How can you create an API route and use it to verify and process a webhook from Kontent?


Ondrej PolesnyJan 24, 2022

In this article, I will explain what webhooks are used for, show how to process them, and verify their source in Next.js.

What is a webhook notification?

Webhook is simply an HTTP request—a notification whenever something happens. Let’s say you publish a new content item. Then, you may need to rebuild your site, update a search index, or tweet about the new content on Twitter. The code that handles these use cases is invoked by the webhook notification issued by the Kontent headless CMS.

How are webhooks secured?

The webhook notification travels through the internet to a defined destination—that’s where you deployed your code. The code needs to be publicly available, so you should always check the webhook origin by analyzing the request signature.

Kontent by Kentico

The signature is a hash of the request payload and your chosen secret that you can configure in Kontent. Whenever a webhook gets dispatched, Kontent will calculate the hash and assign it the X-KC-Signature header value. In your code, you should do the same and check that the signatures match.

Implementing the signature check

Let’s see how we can do that in Next.js. First, we’ll add the API route to the Next.js site. Create a new file update.ts under /pages/api and add the following:

export default async (req: NextApiRequest, res: NextApiResponse) {
}

This will create an API route at /api/update that currently won’t do anything.

Then, we’ll install the Kontent Webhook JS helper containing functions that generate the signature for us:

npm i @kentico/kontent-webhook-helper

To verify the signature of the request, we need three components:

  • The secret we configured in Kontent
    The randomly generated string we can just copy-paste from Kontent into .env file:
WEBHOOK_SECRET=t9BXdUFfYmYkekyzPS1okZLhDbGD44uOD1/7CILu4Iw=
  • The signature from the request header
    We can get that from the req variable:
const signature = req.headers['x-kc-signature']?.toString()
  • The request payload in raw form
    We need the raw body as every whitespace changes the output of the hash function. And that’s a bit tricky as Next.js automatically parses the body for every API request.

Getting the raw body of API request in Next.js

To get a raw body in Next.js, we first need to disable the default body parser:

export default async (req: NextApiRequest, res: NextApiResponse) {
}

export const config = {
  api: {
    bodyParser: false,
  },
}

Then, we’ll install micro by Vercel:

npm i micro

The library will allow us to get the raw body as a string. Typically, we also want to work with the data in the body, so we’ll also parse the body using JSON.parse:

import { buffer } from 'micro'

export default async (req: NextApiRequest, res: NextApiResponse) {
  const body = (await buffer(req)).toString()
  const data = JSON.parse(body)
}

...

Now we finally have all the components for the webhook helper, so we’ll let it generate the hash and compare it with the one provided by the request header using the isValidSignatureFromString function. This is the full final code:

import { buffer } from 'micro'
import { signatureHelper } from '@kentico/kontent-webhook-helper'

export default async (req: NextApiRequest, res: NextApiResponse) {
  const rawBody = (await buffer(req)).toString()
  const data = JSON.parse(rawBody)
  const signature = req.headers['x-kc-signature']?.toString()

  if (!signature
        && !signatureHelper.isValidSignatureFromString(rawBody, process.env.WEBHOOK_SECRET, signature) {
    return res.status(401)
  }

  // signature verified, continue processing the webhook
}

export const config = {
  api: {
    bodyParser: false,
  },
}

And that’s it! 💪 

You can now deploy this API route and configure the endpoint in Kontent. Only Kontent-generated requests will be authorized and processed.

Conclusion

In this article, I showed you how to create a new API route in Next.js and protect it so that it only processes webhook notifications from Kontent.

I hope you’re having a lot of fun with Next.js. If you need some help or want to discuss your project, make sure to join our community on Discord!

Written by

Ondrej Polesny

As Developer Evangelist, I specialize in the impossible. When something is too complicated, requires too much effort, or is just simply not possible, just give me a few days and we will see :).

More articles from Ondrej