mailersend-nodejs icon indicating copy to clipboard operation
mailersend-nodejs copied to clipboard

Add a code sample to verify a webhook signature

Open Agathe-Brusset opened this issue 1 year ago • 1 comments

We have information on how to verify a signature in PHP but do not provide more code examples, please provide one and share here so we can publish it to the dev docs.

Agathe-Brusset avatar Mar 11 '24 14:03 Agathe-Brusset

Here's how I did it for Go:

package webhook

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"io"
	"net/http"
)

func Handle(w http.ResponseWriter, r *http.Request) {
	hash := hmac.New(sha256.New, []byte("<WEBHOOK_SECRET>"))
	body := bytes.NewBuffer(nil)
	reader := http.MaxBytesReader(r.Body, http.DefaultMaxHeaderBytes)

	// Use io.MultiWriter so you can decode the request payload using the "body" variable
	// once the signature is validated.
	if _, err := io.Copy(io.MultiWriter(hash, payload), reader); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	if hex.EncodeToString(hash.Sum(nil)) != r.Header.Get("Signature") {
		http.Error(w, "invalid signature", http.StatusForbidden)
		return
	}
}

I had to reverse engineer it a bit using the PHP example so it would be good to have it documented.

davidsbond avatar Aug 04 '24 01:08 davidsbond

Example for JS cc @Agathe-Brusset

import crypto from 'crypto'

const computedSignature = crypto
    .createHmac('sha256', signingSecret)
    .update(requestContent, 'utf8')
    .digest('hex');

return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(computedSignature, 'hex')
);

PeterOcansey avatar May 14 '25 12:05 PeterOcansey