MCPcopy Index your code
hub / github.com/simstudioai/sim / verifyLoopsSignature

Function verifyLoopsSignature

apps/sim/lib/webhooks/providers/loops.ts:26–58  ·  view source on GitHub ↗

* Verify a Loops webhook signature. * Loops uses a Svix-compatible signing scheme (its own implementation, not Svix-hosted): * HMAC-SHA256 of `${webhookId}.${timestamp}.${body}` signed with the base64-decoded signing * secret (provided as `prefix_base64string`). Delivery metadata arrives in the `

(
  secret: string,
  webhookId: string,
  timestamp: string,
  signatureHeader: string,
  rawBody: string
)

Source from the content-addressed store, hash-verified

24 * @see https://loops.so/docs/webhooks
25 */
26function verifyLoopsSignature(
27 secret: string,
28 webhookId: string,
29 timestamp: string,
30 signatureHeader: string,
31 rawBody: string
32): boolean {
33 try {
34 const ts = Number.parseInt(timestamp, 10)
35 const now = Math.floor(Date.now() / 1000)
36 if (Number.isNaN(ts) || Math.abs(now - ts) > LOOPS_WEBHOOK_TIMESTAMP_SKEW_SECONDS) {
37 return false
38 }
39
40 const base64Secret = secret.includes('_') ? secret.slice(secret.indexOf('_') + 1) : secret
41 const secretBytes = Buffer.from(base64Secret, 'base64')
42 const toSign = `${webhookId}.${timestamp}.${rawBody}`
43 const expectedSignature = hmacSha256Base64(toSign, secretBytes)
44
45 const providedSignatures = signatureHeader.split(' ')
46 for (const versionedSig of providedSignatures) {
47 const parts = versionedSig.split(',')
48 const sig = parts.length === 2 ? parts[1] : versionedSig
49 if (sig && safeCompare(sig, expectedSignature)) {
50 return true
51 }
52 }
53 return false
54 } catch (error) {
55 logger.error('Error verifying Loops signature:', error)
56 return false
57 }
58}
59
60export const loopsHandler: WebhookProviderHandler = {
61 async verifyAuth({

Callers 1

verifyAuthFunction · 0.85

Calls 3

hmacSha256Base64Function · 0.90
safeCompareFunction · 0.90
errorMethod · 0.80

Tested by

no test coverage detected