Skip to content

Commit c656270

Browse files
royangerwobsorianoLekoArts
authored
fix(backend): Remove peerDep of svix for verifyWebhook() (#6059)
Co-authored-by: Robert Soriano <sorianorobertc@gmail.com> Co-authored-by: Lennart <lekoarts@gmail.com>
1 parent 918e2e0 commit c656270

File tree

4 files changed

+37
-58
lines changed

4 files changed

+37
-58
lines changed

.changeset/hungry-mangos-shout.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
'@clerk/backend': minor
3+
'@clerk/astro': minor
4+
'@clerk/express': minor
5+
'@clerk/fastify': minor
6+
'@clerk/nextjs': minor
7+
'@clerk/nuxt': minor
8+
'@clerk/react-router': minor
9+
'@clerk/tanstack-react-start': minor
10+
---
11+
12+
The `svix` dependency is no longer needed when using the `verifyWebhook()` function. `verifyWebhook()` was refactored to not rely on `svix` anymore while keeping the same functionality and behavior.
13+
14+
If you previously installed `svix` to use `verifyWebhook()` you can uninstall it now:
15+
16+
```shell
17+
npm uninstall svix
18+
```

packages/backend/package.json

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,17 +117,8 @@
117117
"@edge-runtime/vm": "5.0.0",
118118
"msw": "2.8.7",
119119
"npm-run-all": "^4.1.5",
120-
"svix": "^1.66.0",
121120
"vitest-environment-miniflare": "2.14.4"
122121
},
123-
"peerDependencies": {
124-
"svix": "^1.62.0"
125-
},
126-
"peerDependenciesMeta": {
127-
"svix": {
128-
"optional": true
129-
}
130-
},
131122
"engines": {
132123
"node": ">=18.17.0"
133124
},

packages/backend/src/webhooks.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { getEnvVariable } from '@clerk/shared/getEnvVariable';
2+
import crypto from 'crypto';
23
import { errorThrower } from 'src/util/shared';
3-
import { Webhook } from 'svix';
44

55
import type { WebhookEvent } from './api/resources/Webhooks';
66

@@ -71,12 +71,24 @@ export async function verifyWebhook(request: Request, options: VerifyWebhookOpti
7171
return errorThrower.throw(`Missing required Svix headers: ${missingHeaders.join(', ')}`);
7272
}
7373

74-
const sivx = new Webhook(secret);
7574
const body = await request.text();
7675

77-
return sivx.verify(body, {
78-
[SVIX_ID_HEADER]: svixId,
79-
[SVIX_TIMESTAMP_HEADER]: svixTimestamp,
80-
[SVIX_SIGNATURE_HEADER]: svixSignature,
81-
}) as WebhookEvent;
76+
const signedContent = `${svixId}.${svixTimestamp}.${body}`;
77+
78+
const secretBytes = Buffer.from(secret.split('_')[1], 'base64');
79+
80+
const constructedSignature = crypto.createHmac('sha256', secretBytes).update(signedContent).digest('base64');
81+
82+
// svixSignature can be a string with one or more space separated signatures
83+
if (svixSignature.split(' ').includes(constructedSignature)) {
84+
return errorThrower.throw('Incoming webhook does not have a valid signature');
85+
}
86+
87+
const payload = JSON.parse(body);
88+
89+
return {
90+
type: payload.type,
91+
object: 'event',
92+
data: payload.data,
93+
} as WebhookEvent;
8294
}

pnpm-lock.yaml

Lines changed: 0 additions & 42 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)