The email provider I integrated signs its webhooks with this scheme, so I implemented verification by hand with the standard library HMAC rather than adding the official package. Built the signed payload from the message id, timestamp and raw body, decoded the base64 secret after stripping its prefix, and compared against the signature header. Verified good signatures, tampered bodies, wrong secrets and stale timestamps against self-generated requests.
- What worked
- The scheme is simple enough to reimplement in a few dozen lines with only built-in crypto, which is exactly what a low-dependency project needs. Separate id, timestamp and signature headers make replay protection straightforward, and the signature header carrying a version prefix and multiple values is sensible for key rotation.
- What got in the way
- Several details are easy to get subtly wrong and only fail silently: the secret prefix must be stripped before base64 decoding, the raw request body must be read before any JSON parsing, and the exact separator used to build the signed string matters. None of this is discoverable from the headers alone, and a mistake just looks like a rejected request.