Validating the Webhook Signature

JavaScript / NodeJS Example

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

app.use(express.json());

app.post('/authenticate', async (req, res) => {
    const hashSecret = "your_secret_here"; // Replace with your secret
    const signatureHeaderKey = req.headers['quickbuy-signature'];

    const rawBody = JSON.stringify(req.body); // Assuming JSON body
    const rawSignature = rawBody + hashSecret;
    
    const sha256 = crypto.createHash('sha256');
    const keyToAccept = sha256.update(Buffer.from(rawSignature, 'utf8')).digest('base64');

    if (keyToAccept === signatureHeaderKey) {
        res.send("Authenticated");
    } else {
        res.status(401).send("Authentication failed");
    }
});

Python Example

import hashlib
import base64
import json

async def authenticate():
    hash_secret = "your_secret_here" # Replace with your secret
    signature_header_key = request.headers.get('QuickBuy-Signature')

    raw_body = json.dumps(request.json) # Assuming JSON body
    raw_signature = (raw_body + hash_secret).encode()

    sha256 = hashlib.sha256()
    sha256.update(raw_signature)
    key_to_accept = base64.b64encode(sha256.digest()).decode()

    if key_to_accept == signature_header_key:
        return "Authenticated"
    else:
        return "Authentication failed", 401

C# ASP.NET Example

using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;

public class Authentication
{
    public async Task<bool> AuthenticateRequest(string hashSecret, HttpContext httpContext)
    {
        if (!httpContext.Request.Headers.TryGetValue("QuickBuy-Signature", out var headerKey))
        {
            return false;
        }

        using var ms = new MemoryStream();
        await httpContext.Request.Body.CopyToAsync(ms);
        var bodyBytes = ms.ToArray();

        var rawSignature = bodyBytes.Concat(Encoding.UTF8.GetBytes(hashSecret)).ToArray();
        using var sha256 = SHA256.Create();
        var keyToAccept = Convert.ToBase64String(sha256.ComputeHash(rawSignature));

        return keyToAccept == headerKey.FirstOrDefault();
    }
}

Go Example

package main

import (
	"crypto/sha256"
	"encoding/base64"
	"io"
	"io/ioutil"
	"net/http"
)

func authenticateRequest(w http.ResponseWriter, r *http.Request, hashSecret string) {
	headerKey := r.Header.Get("QuickBuy-Signature")
	if headerKey == "" {
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
		return
	}

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}
	defer r.Body.Close()

	rawSignature := append(body, []byte(hashSecret)...)
	hasher := sha256.New()
	hasher.Write(rawSignature)
	keyToAccept := base64.StdEncoding.EncodeToString(hasher.Sum(nil))

	if keyToAccept == headerKey {
		w.Write([]byte("Authenticated"))
	} else {
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
	}
}

func main() {
	http.HandleFunc("/authenticate", func(w http.ResponseWriter, r *http.Request) {
		authenticateRequest(w, r, "your_secret_here") // Replace with your secret
	})

	http.ListenAndServe(":3000", nil)
}

Last updated