Skip to content

Webhooks Security

Secure your webhook endpoints to verify requests from Islamic Open Finance™.

Signature Verification

All webhook requests include a signature header:

X-IOF-Signature: t=1234567890,v1=abc123...

Verification Steps

  1. Extract timestamp and signature from header
  2. Prepare the signed payload
  3. Compute expected signature
  4. Compare signatures

Node.js Example

typescript
import crypto from "crypto";

function verifyWebhook(
  payload: string,
  signature: string,
  secret: string,
): boolean {
  const [timestamp, sig] = signature
    .split(",")
    .map((part) => part.split("=")[1]);

  const signedPayload = `${timestamp}.${payload}`;
  const expectedSig = crypto
    .createHmac("sha256", secret)
    .update(signedPayload)
    .digest("hex");

  return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expectedSig));
}

Using the SDK

typescript
import { IslamicOpenFinance } from "@iof/sdk";

const iof = new IslamicOpenFinance({ apiKey: "..." });

app.post("/webhooks", (req, res) => {
  const isValid = iof.webhooks.verify(
    req.body,
    req.headers["x-iof-signature"],
    process.env.WEBHOOK_SECRET,
  );

  if (!isValid) {
    return res.status(401).send("Invalid signature");
  }

  // Process webhook
});

Timestamp Validation

Reject requests older than 5 minutes:

typescript
const timestamp = parseInt(parts[0].split("=")[1]);
const now = Math.floor(Date.now() / 1000);

if (now - timestamp > 300) {
  throw new Error("Request too old");
}

IP Allowlisting

Webhook requests come from these IP ranges:

52.20.0.0/16
54.160.0.0/16

Best Practices

  1. Always verify signatures
  2. Use HTTPS endpoints only
  3. Respond quickly (< 30s)
  4. Implement idempotency
  5. Log all webhook events

Next Steps

Licensed under the Apache License 2.0