Skip to content

Conversation

@wobsoriano
Copy link
Member

@wobsoriano wobsoriano commented Mar 27, 2025

Description

Right now, customers have to implement webhook verification when receiving Clerk webhooks to sync data with their apps using this guide. This PR abstracts away the majority of that logic, and makes it built-in across our backend and full-stack SDKs.

The verification can now be done with a single function call:

import { verifyWebhook } from '@clerk/backend/webhooks';
// Or from your framework-specific package:
// import { verifyWebhook } from '@clerk/nextjs/webhooks';

try {
  const evt = await verifyWebhook(request);
  if (evt.type === 'user.created') {
    // Handle user creation
    console.log('New user created:', evt.data.id);
  }
} catch (err) {
  // Invalid webhook signature
  return new Response('Webhook verification failed', { status: 400 });
}

Most of our SDKs provide a web standard Request object that can be passed directly to the verifyWebhook function. For Express and Fastify, we've added framework-specific support so that users can pass their route request object directly.

We also marked svix as an optional peer dependency for users not using webhooks.

Did some local tests to the ff. SDKs:

  • ✅ Express
  • ✅ Fastify
  • ✅ Nuxt
  • ✅ Nextjs

Resolves ECO-533

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

@changeset-bot
Copy link

changeset-bot bot commented Mar 27, 2025

🦋 Changeset detected

Latest commit: 2a73cdc

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
@clerk/tanstack-react-start Minor
@clerk/fastify Minor
@clerk/react-router Minor
@clerk/backend Minor
@clerk/express Minor
@clerk/nextjs Minor
@clerk/astro Minor
@clerk/nuxt Minor
@clerk/agent-toolkit Patch
@clerk/remix Patch
@clerk/testing Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Mar 27, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
clerk-js-sandbox ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 3, 2025 3:51am

@wobsoriano wobsoriano changed the title feat(backend): Add verify webhook function feat(backend,react-router,nuxt,astro,nextjs): Add verify webhook function Mar 27, 2025
@wobsoriano wobsoriano changed the title feat(backend,react-router,nuxt,astro,nextjs): Add verify webhook function feat(backend,react-router,nuxt,astro,nextjs,tanstack-react-start): Add verify webhook function Mar 27, 2025
@wobsoriano wobsoriano changed the title feat(backend,react-router,nuxt,astro,nextjs,tanstack-react-start): Add verify webhook function feat(backend,react-router,nuxt,astro,nextjs,tanstack-react-start,express,fastify): Add verify webhook function Mar 27, 2025
@clerk clerk deleted a comment from clerk-cookie Mar 27, 2025
}

if (!svixId || !svixTimestamp || !svixSignature) {
return errorThrower.throw('Missing required Svix headers.');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless intended, a nice DX touch would be to inform the user which header is missing

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to have more info about missing headers!

wobsoriano and others added 4 commits April 2, 2025 08:57
Co-authored-by: Lennart <lekoarts@gmail.com>
Co-authored-by: Lennart <lekoarts@gmail.com>
Co-authored-by: Lennart <lekoarts@gmail.com>
Co-authored-by: Lennart <lekoarts@gmail.com>
Copy link
Member

@brkalow brkalow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👏 left one minor comment, otherwise LGTM

const svixSignature = request.headers.get(SVIX_SIGNATURE_HEADER);

if (!secret) {
return errorThrower.throw('Missing signing secret. Please add it to your environment variables.');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use the actual env var name here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯 updated!

@wobsoriano wobsoriano merged commit cd6ee92 into main Apr 3, 2025
30 checks passed
@wobsoriano wobsoriano deleted the rob/eco-533-internal-verify-webhook branch April 3, 2025 04:02
@LekoArts
Copy link
Contributor

LekoArts commented Apr 3, 2025

Nice 👏

@mlafeldt
Copy link
Contributor

mlafeldt commented Apr 9, 2025

@wobsoriano Hey, I just wanted to bring svix/svix-webhooks#1483 to your attention. Using svix instead of standardwebhooks (also by the Svix guys) will significantly impact bundle size. Switching packages is actually pretty straightforward. See my comments in the linked issue.

@wobsoriano
Copy link
Member Author

@wobsoriano Hey, I just wanted to bring svix/svix-webhooks#1483 to your attention. Using svix instead of standardwebhooks (also by the Svix guys) will significantly impact bundle size. Switching packages is actually pretty straightforward. See my comments in the linked issue.

This is noted 🫡

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants