HTTP signature on Webhooks

A-Cube applies a digital signature to each http call directed to the customer's system

The signature implements the IETF HTTP Message Signatures draft standard

Here you can make some tests and you can also find a list of libraries to verify the signature with different languages.

Http headers added to each call

Every API call to your webhook will contain 3 headers related to the HTTP signature:

  • signature
  • signature-input
  • content-digest

Example:

Copy
Copied
signature       pyhms=:AaMvAaBdJ2cUFmbOphvpoNTyu0uXAaQjIZXTweRl6hseuHNRpdPYA14EDJCBnnBXbcaOjiZ9F137wP6fBhN6CA==: signature-input pyhms=("@method" "@authority" "@target-uri" "date" "content-digest");created=1677383376;keyid="acube";alg="ed25519" content-digest sha-256=:Qm/ATwS/j9tYMdw3u7bc9w9jo34FpoxupfY+ha5Xk3Y=:

Public key. Key id: acube

Use this public key to verify the content sent by A-Cube API platform to your webhook.

For sandbox:

Public key

Loading public key...

Public key

Loading public key...

For production:

Public key

Loading public key...

Public key

Loading public key...

Examples of signature verification

Python

bashpython
Copy
Copied
pip install "fastapi[all]"
pip install requests
pip install requests-http-signature
Copy
Copied
import requests
from fastapi import FastAPI, Request, HTTPException
from requests_http_signature import (
    HTTPSignatureAuth,
    InvalidSignature,
    algorithms,
)

app = FastAPI()

class KeyResolver:
    def resolve_public_key(self, key_id):
        if key_id != "acube":
            raise HTTPException(status_code=401, detail="Invalid http signature: key_id doesn't match")
        return requests.get("https://common-sandbox.api.acubeapi.com/signature-public-key").json()["public_key"]


@app.post("/my_webhook")
async def my_webhook(request: Request):
    class RequestData:
        async def fill(self, request):
            self.body = await request.body()
            self.headers = request.headers
            self.url = str(request.url)
            self.method = request.method
            return self
    requestData = await RequestData().fill(request)

    try:
        HTTPSignatureAuth.verify(
            requestData,
            signature_algorithm=algorithms.ED25519,
            key_resolver=KeyResolver(),
        )

        return {"message": "done"}

    except InvalidSignature:
        raise HTTPException(status_code=401, detail="Invalid http signature")

Typescript

We created a sample repository with a demo Typescript application that verifies the signature we apply to webhooks calls.