UNPKG

eve

Version:

Filesystem-first framework for durable backend AI agents that run anywhere.

1 lines 1.46 kB
import{createLogger}from"#internal/logging.js";import{createHmac,timingSafeEqual}from"node:crypto";const log=createLogger(`twilio.verify`);async function resolveTwilioAuthToken(e){let t=e??process.env.TWILIO_AUTH_TOKEN;if(!t)throw Error(`TWILIO_AUTH_TOKEN is required.`);return typeof t==`function`?await t():t}async function verifyTwilioRequest(e,t){let n=await e.text(),r=new URLSearchParams(n),i=await resolveTwilioAuthToken(t.authToken),a=e.headers.get(`x-twilio-signature`)??``;if(!a)throw Error(`twilioChannel: inbound request missing X-Twilio-Signature.`);if(!constantTimeCompare(signTwilioRequest({authToken:i,params:r,url:await resolveWebhookUrl(e,t.webhookUrl)}),a))throw Error(`twilioChannel: inbound request signature mismatch.`);return{body:n,params:r}}function signTwilioRequest(e){let n=buildTwilioSignatureBase(e.url,e.params);return createHmac(`sha1`,e.authToken).update(n).digest(`base64`)}function buildTwilioSignatureBase(e,t){let n=Array.from(t.entries()).sort(([e,t],[n,r])=>{let i=e<n?-1:+(e>n);return i===0?t<r?-1:+(t>r):i}),r=e;for(let[e,t]of n)r+=`${e}${t}`;return r}async function resolveWebhookUrl(e,t){return typeof t==`function`?t(e):t??e.url}function constantTimeCompare(e,t){if(e.length!==t.length)return!1;try{return timingSafeEqual(Buffer.from(e),Buffer.from(t))}catch(e){return log.debug(`timingSafeEqual threw`,{error:e}),!1}}export{buildTwilioSignatureBase,resolveTwilioAuthToken,signTwilioRequest,verifyTwilioRequest};