test(voice-call): share signed telnyx request helper

This commit is contained in:
Vincent Koc
2026-04-12 05:31:25 +01:00
parent 560d56e8fd
commit 97aa6e0815

View File

@@ -145,6 +145,36 @@ function verifyTwilioSignedRequest(params: {
);
}
function createSignedTelnyxWebhookRequest() {
const { publicKey, privateKey } = crypto.generateKeyPairSync("ed25519");
const pemPublicKey = publicKey.export({ format: "pem", type: "spki" });
const timestamp = String(Math.floor(Date.now() / 1000));
const rawBody = JSON.stringify({
data: { event_type: "call.initiated", payload: { call_control_id: "call-1" } },
nonce: crypto.randomUUID(),
});
const signedPayload = `${timestamp}|${rawBody}`;
const signature = crypto.sign(null, Buffer.from(signedPayload), privateKey).toString("base64");
return {
pemPublicKey,
timestamp,
rawBody,
signature,
makeCtx(signatureValue = signature) {
return {
headers: {
"telnyx-signature-ed25519": signatureValue,
"telnyx-timestamp": timestamp,
},
rawBody,
url: "https://example.com/voice/webhook",
method: "POST" as const,
};
},
};
}
describe("verifyPlivoWebhook", () => {
it("accepts valid V2 signature", () => {
const authToken = "test-auth-token";
@@ -368,66 +398,22 @@ describe("verifyPlivoWebhook", () => {
describe("verifyTelnyxWebhook", () => {
it("marks replayed valid requests as replay without failing auth", () => {
const { publicKey, privateKey } = crypto.generateKeyPairSync("ed25519");
const pemPublicKey = publicKey.export({ format: "pem", type: "spki" });
const timestamp = String(Math.floor(Date.now() / 1000));
const rawBody = JSON.stringify({
data: { event_type: "call.initiated", payload: { call_control_id: "call-1" } },
nonce: crypto.randomUUID(),
});
const signedPayload = `${timestamp}|${rawBody}`;
const signature = crypto.sign(null, Buffer.from(signedPayload), privateKey).toString("base64");
const ctx = {
headers: {
"telnyx-signature-ed25519": signature,
"telnyx-timestamp": timestamp,
},
rawBody,
url: "https://example.com/voice/webhook",
method: "POST" as const,
};
const request = createSignedTelnyxWebhookRequest();
const first = verifyTelnyxWebhook(ctx, pemPublicKey);
const second = verifyTelnyxWebhook(ctx, pemPublicKey);
const first = verifyTelnyxWebhook(request.makeCtx(), request.pemPublicKey);
const second = verifyTelnyxWebhook(request.makeCtx(), request.pemPublicKey);
expectReplayResultPair(first, second);
});
it("treats Base64 and Base64URL signatures as the same replayed request", () => {
const { publicKey, privateKey } = crypto.generateKeyPairSync("ed25519");
const pemPublicKey = publicKey.export({ format: "pem", type: "spki" });
const timestamp = String(Math.floor(Date.now() / 1000));
const rawBody = JSON.stringify({
data: { event_type: "call.initiated", payload: { call_control_id: "call-1" } },
nonce: crypto.randomUUID(),
});
const signedPayload = `${timestamp}|${rawBody}`;
const signature = crypto.sign(null, Buffer.from(signedPayload), privateKey).toString("base64");
const urlSafeSignature = signature.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
const first = verifyTelnyxWebhook(
{
headers: {
"telnyx-signature-ed25519": signature,
"telnyx-timestamp": timestamp,
},
rawBody,
url: "https://example.com/voice/webhook",
method: "POST" as const,
},
pemPublicKey,
);
const second = verifyTelnyxWebhook(
{
headers: {
"telnyx-signature-ed25519": urlSafeSignature,
"telnyx-timestamp": timestamp,
},
rawBody,
url: "https://example.com/voice/webhook",
method: "POST" as const,
},
pemPublicKey,
);
const request = createSignedTelnyxWebhookRequest();
const urlSafeSignature = request.signature
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/g, "");
const first = verifyTelnyxWebhook(request.makeCtx(), request.pemPublicKey);
const second = verifyTelnyxWebhook(request.makeCtx(urlSafeSignature), request.pemPublicKey);
expectReplayResultPair(first, second);
});