Skip to content

Security

Principles

  1. We never send back analysis results or transaction data over webhooks. An API client has to explicitly request that data through the Navigator API. From our perspective, we cannot ensure that the webhook endpoint belongs to you, even though it is specified by you. Therefore, we only ever send out minimally useful information (events).

  2. A webhook request contains a signature in the X-Navigator-Signature HTTP-header that can be verified with the code below. It allows you to ensure that the request came from RiskQuest Navigator and not some other party.

  3. The webhook URL can only be called over HTTPS. We do not allow creating a webhook with HTTP.

Verifying request authenticity

The Python script below encapsulates our response payload signature and verification code. It can be used to validate our signatures from your side.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import hashlib
import hmac
from datetime import datetime, timezone
from typing import Optional


def make_signature(secret: str, payload: str, timestamp: Optional[int] = None) -> str:
    if timestamp is None:
        timestamp = int(datetime.now(timezone.utc).timestamp())
    signature_payload = f"{timestamp}." + payload
    signature = hmac.new(
        secret.encode("utf-8"),
        signature_payload.encode("utf-8"),
        hashlib.sha256,
    ).hexdigest()

    return f"t={timestamp},v1={signature}"


def verify_signature(secret: str, payload: str, signature: str) -> bool:
    signature_parts = signature.split(",")
    timestamp = int(signature_parts[0].split("=")[1])
    sig_version, actual_signature = signature_parts[1].split("=")

    if sig_version != "v1":
        return False

    expected_sig = make_signature(secret, payload, timestamp)
    return expected_sig == signature


secret = "abc"
payload = "{'hello': 'world'}"
sig = make_signature(secret, payload)
print(verify_signature(secret, payload, sig))