Webhook Verification

The SDK provides utilities to verify webhook signatures, ensuring that incoming webhook payloads genuinely originated from Felloh.


Verifying Signatures

Felloh signs every webhook request with an HMAC-SHA256 signature sent in the X-Signature header. The SDK provides two functions to verify this signature:

  • verifyWebhookSignature — returns true or false
  • assertWebhookSignature — throws FellohWebhookSignatureError if invalid

Both use timing-safe comparison to prevent timing attacks.

Parameters

  • Name
    payloadrequired
    Type
    string | Buffer
    Description

    The raw request body. Must not be parsed or modified — use the raw body as received.

  • Name
    signaturerequired
    Type
    string
    Description

    The value of the X-Signature header from the webhook request.

  • Name
    secretrequired
    Type
    string
    Description

    Your webhook signing secret from the Felloh dashboard.

Boolean Check

import { verifyWebhookSignature } from '@felloh-org/node-sdk';

const isValid = verifyWebhookSignature({
  payload: rawRequestBody,
  signature: req.headers['x-signature'],
  secret: 'your-webhook-secret',
});

if (!isValid) {
  res.status(401).send('Invalid signature');
  return;
}

// Process the webhook...

Assert (throws on failure)

import { assertWebhookSignature } from '@felloh-org/node-sdk';

try {
  assertWebhookSignature({
    payload: rawRequestBody,
    signature: req.headers['x-signature'],
    secret: 'your-webhook-secret',
  });
} catch (err) {
  // err is FellohWebhookSignatureError
  res.status(401).send('Invalid signature');
  return;
}

// Signature is valid, process the webhook...

Express Example

When using Express, you must access the raw request body for signature verification. Use express.raw() or express.text() on the webhook route to prevent body parsing from modifying the payload.

Express Webhook Handler

import express from 'express';
import { assertWebhookSignature } from '@felloh-org/node-sdk';

const app = express();

app.post(
  '/webhooks/felloh',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    try {
      assertWebhookSignature({
        payload: req.body,
        signature: req.headers['x-signature'],
        secret: process.env.FELLOH_WEBHOOK_SECRET,
      });
    } catch (err) {
      return res.status(401).send('Invalid signature');
    }

    const event = JSON.parse(req.body.toString());
    console.log('Webhook received:', event);

    res.status(200).send('OK');
  }
);