From cee3f533f4ab4ea8848afa4f6c0b4b87a8505e3e Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 6 Apr 2019 13:05:59 -0400 Subject: Document webhook signatures --- api-conventions.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/api-conventions.md b/api-conventions.md index 3dbd479..e44b446 100644 --- a/api-conventions.md +++ b/api-conventions.md @@ -178,6 +178,31 @@ resource is encoded via the API. `X-Webhook-Delivery` is set to a UUID assigned to that webhook delivery, and `X-Webhook-Event` is set to the specific event that occurred, e.g. `profile:update`. +### Webhook signatures + +The `X-Payload-Signature` and `X-Payload-Nonce` headers can be used to verify +the authenticity of the webhook payload. Concatenate the request body with the +nonce (treat the nonce as an ASCII-encoded string) and use it to verify the +base64-encoded Ed25519 siganture given by the `X-Payload-Signature` header. The +public key (also base64 encoded) is +`uX7KWyyDNMaBma4aVbJ/cbUQpdjqczuCyK/HxzV/u+4=`. Here's an example of verifying +the payload in Python: + +```python +import base64 +from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey + +public_key = Ed25519PublicKey.from_public_bytes( + base64.b64decode('uX7KWyyDNMaBma4aVbJ/cbUQpdjqczuCyK/HxzV/u+4=')) + +payload = request.data +signature = headers["X-Payload-Signature"] +signature = base64.b64decode(signature) +nonce = headers["X-Payload-Signature"].encode() + +public_key.verify(signature, payload + nonce) +``` + ### Subscription resource ```json -- cgit