From 97aa6e0815dfbb1a6697e6af822b746776b3e54a Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 12 Apr 2026 05:31:25 +0100 Subject: [PATCH] test(voice-call): share signed telnyx request helper --- .../voice-call/src/webhook-security.test.ts | 94 ++++++++----------- 1 file changed, 40 insertions(+), 54 deletions(-) diff --git a/extensions/voice-call/src/webhook-security.test.ts b/extensions/voice-call/src/webhook-security.test.ts index e85c27a2b55..de9465824ac 100644 --- a/extensions/voice-call/src/webhook-security.test.ts +++ b/extensions/voice-call/src/webhook-security.test.ts @@ -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); });