Skip to main content

Clerk Changelog

Dashboard accounts now start as an organization, as opposed to Personal accounts.

Previously, new users on the Clerk Dashboard started with "personal accounts." This meant that to add collaborators, you first had to convert your account to an Organization. Since July 4th, all new Dashboard users have been automatically set up with an organization, allowing you to invite team members and collaborate immediately.

For existing users, we will automatically migrate your personal account and all its resources to an organization in the coming days. No action is required on your part—all your applications and settings will remain unchanged.

This change only affects Clerk Dashboard users and has no impact on your applications or its users.

Contributor
Clerk

Share this article

CVE-2025-53548

Category
Security
Published

Summary

A vulnerability affecting @clerk/backend >= 2.0.0 < 2.4.0 was recently reported to the Clerk team and resolved. The vulnerability was discovered in the verifyWebhook() helper, which is used to verify incoming Clerk webhooks, and it allowed improperly signed webhook events to be accepted as legitimate. Potentially impacted customers have already been notified via email. If your application does not use verifyWebhook() you are not impacted.

Impact

Applications that use the verifyWebhook() helper to verify incoming Clerk webhooks are susceptible to accepting improperly signed webhook events.

Patches

  • @clerk/backend: the helper has been patched as of 2.4.0
  • @clerk/astro: the helper has been patched as of 2.10.2
  • @clerk/express: the helper has been patched as of 1.7.4
  • @clerk/fastify: the helper has been patched as of 2.4.4
  • @clerk/nextjs: the helper has been patched as of 6.23.3
  • @clerk/nuxt: the helper has been patched as of 1.7.5
  • @clerk/react-router: the helper has been patched as of 1.6.4
  • @clerk/remix: the helper has been patched as of 4.8.5
  • @clerk/tanstack-react-start: the helper has been patched as of 0.18.3

Resolution

The issue was resolved in @clerk/backend 2.4.0 by:

  • Properly parsing the webhook request's signatures and comparing them against the signature generated from the received event

Workarounds

If unable to upgrade, developers can workaround this issue by verifying webhooks manually, per this documentation.

Credits

Thanks to a Clerk customer for responsibly disclosing the issue to the team.

References

Contributor
Bryce Kalow

Share this article

CSS variables support

Category
Product
Published

Clerk's appearance system now supports CSS variables for seamless design system integration and dynamic theming

Clerk's appearance variables object now supports CSS custom properties (CSS variables), making it easier to integrate with your existing design system and enable dynamic theming without JavaScript configuration changes.

How to use CSS variables

You can now use CSS variables directly in your appearance configuration:

styles/globals.css
:root {
  --brand-primary: oklch(49.1% 0.27 292.581);
}

@media (prefers-color-scheme: dark) {
  :root {
    --brand-primary: oklch(54.1% 0.281 293.009);
  }
}

Reference these variables in your Clerk configuration:

app/layout.tsx
<ClerkProvider
  appearance={{
    variables: {
      colorPrimary: 'var(--brand-primary)',
    },
  }}
>
  ...
</ClerkProvider>

Dynamic Theming

With CSS variables, your theme changes automatically based on user preferences, system settings, or any other CSS-driven logic:

/* Theme automatically updates based on user preference */
@media (prefers-color-scheme: dark) {
  :root {
    --brand-primary: oklch(54.1% 0.281 293.009);
  }
}

/* Or with data attributes */
[data-theme='corporate'] {
  --brand-primary: #1e40af;
}

[data-theme='creative'] {
  --brand-primary: #7c3aed;
}

No need to swap Clerk themes or update JavaScript configuration - the components automatically pick up the new colors.

Design System Integration

This enhancement makes it seamless to integrate Clerk with existing design systems:

<ClerkProvider
  appearance={{
    variables: {
      colorPrimary: 'var(--ds-color-brand-primary)',
      colorSuccess: 'var(--ds-color-semantic-success)',
      colorDanger: 'var(--ds-color-semantic-error)',
      colorNeutral: 'var(--ds-color-neutral-base)',
    },
  }}
>
  ...
</ClerkProvider>

Note

Clerk's support for CSS variables relies on color-mix() and relative color syntax, which require a modern browser (Chrome 119+, Safari 16.4+, and Firefox 128+). If your application needs to support older browsers, continue using static color values (like #ff0000 or hsl(0, 100%, 50%)) instead of CSS variables, which will use our existing JavaScript-based color manipulation.

To learn more about support for CSS variables, check out the documentation.

Contributors
Tom Milewski
Alex Carpenter
Dylan Staley

Share this article

Increased Backend Rate Limits

Category
API
Published

We’ve increased the Backend API rate limits for production instances to better support your growing workloads! 🚀

Production instances now support 1000 requests per 10 seconds, a 10x increase from before. This change applies across all endpoints, including Create User.

If you're running high-traffic workloads in production, this gives you more headroom without hitting throttling errors.

We're also working on a smarter, more flexible rate limiting system that scales with your app. More on that soon!

Note: Development instances remain at 100 requests per 10 seconds.

Contributor
Alex Ntousias

Share this article

Billing Webhooks

Category
Product
Published

Billing webhooks are now available.

Payment Attempts

Payment attempt webhooks allow you to track successful and failed payments, for both checkouts and recurring charges.

  • paymentAttempt.created
  • paymentAttempt.updated

Subscriptions

A subscription is the top level container unique to each user or organization. Subscription events can help you track billing changes for each of your customers.

  • subscription.created
  • subscription.updated
  • subscription.active
  • subscription.past_due

Subscription Items

Subscription items provide more details about the relationship between a user or organization and a plan. A top level subscription may contain multiple subscription items.

  • subscriptionItem.created
  • subscriptionItem.updated
  • subscriptionItem.active
  • subscriptionItem.canceled
  • subscriptionItem.upcoming
  • subscriptionItem.ended
  • subscriptionItem.abandoned
  • subscriptionItem.incomplete
  • subscriptionItem.past_due

For more details about these webhook events, visit the Event Catalog tab on the Webhooks page in Clerk dashboard.

Contributor
Henry Snopek

Share this article

MCP Server Support for Next.js

Category
Product
Published

Build an MCP service into your application with Clerk and Next.js in 5 minutes

We're excited to announce server-side support for the Model Context Protocol (MCP) in Next.js applications using Clerk authentication. This enables your users to securely grant AI applications like Claude, Cursor, and others access to their data within your app.

What is MCP?

MCP is an open standard that allows AI applications to request permission to access users' private information that would normally require authentication — like emails, private repositories, or application-specific data. This creates new possibilities for AI-powered workflows while keeping users in control of their data access.

If you are building an application using Clerk and would like for your users to be able to grant access to their data to AI applications, you can now do so with Clerk's MCP support 🎉.

Getting Started

Setting up an MCP server in your Next.js app is straightforward with Clerk's modern OAuth provider implementation. Here's an example of how the MCP route handler might look in your Next.js app:

// app/[transport]/route.ts
import { verifyClerkToken } from '@clerk/mcp-tools/next'
import { clerkClient } from '@clerk/nextjs/server'
import { createMcpHandler, experimental_withMcpAuth as withMcpAuth } from '@vercel/mcp-adapter'

const clerk = await clerkClient()

const handler = createMcpHandler((server) => {
  server.tool(
    'get-clerk-user-data',
    'Gets data about the Clerk user that authorized this request',
    {},
    async (_, { authInfo }) => {
      const userId = authInfo!.extra!.userId! as string
      const userData = await clerk.users.getUser(userId)
      return {
        content: [{ type: 'text', text: JSON.stringify(userData) }],
      }
    },
  )
})

const authHandler = withMcpAuth(
  handler,
  async (_, token) => {
    const clerkAuth = await auth({ acceptsToken: 'oauth_token' })
    return verifyClerkToken(clerkAuth, token)
  },
  {
    required: true,
    resourceMetadataPath: '/.well-known/oauth-protected-resource/mcp',
  },
)

export { authHandler as GET, authHandler as POST }

Note

OAuth tokens are machine tokens. Machine token usage is free during our public beta period but will be subject to pricing once generally available. Pricing is expected to be competitive and below market averages.

Implementation Details

Our MCP implementation is built on the current specification draft, ensuring compatibility with the latest protocol standards and authentication flows. We've worked closely with the MCP community and contributed to the specification and SDK to ensure robust, secure integrations.

Rather than requiring separate MCP servers with their own authentication protocols, our approach allows you to add MCP capabilities directly to your existing application through a single API endpoint. This eliminates the overhead of deploying and managing additional services - you can expose your app's functionality to AI tools without architectural complexity.

For legacy clients that use outdated implementations of the MCP protocol and/or do not support authentication, tools like mcp-remote can bridge the gap.

We are also grateful to Vercel for their fantastic work on the MCP Adapter, which this implementation leverages heavily. We've thoroughly enjoyed collaborating with their team on this project.

Connecting AI Tools

Once your MCP server is running, connecting it to AI tools is straightforward. For example, with Cursor, you can add this configuration:

{
  "mcpServers": {
    "clerk-mcp-example": {
      "url": "http://localhost:3000/mcp"
    }
  }
}

That's it — no stdio tools, command execution, or additional software installation required. Just provide the URL and authentication is handled automatically through the MCP protocol.

For a complete guide on testing your MCP server with various AI clients, check out our MCP client integration guide.

Customer Implementations

We've been developing MCP tooling publicly for the past few months and have been impressed by our customers' enthusiasm for building with this technology. The extensive testing and feedback we've received has been invaluable in shaping and stabilizing this release.

We'd like to highlight a couple of examples of customers who have deployed MCP servers with Clerk authentication to production:

These customers have been exceptional development partners, and their engineering teams are working hard to build innovative products and ensure that their users can integrate their products with MCP as easily as possible. We're proud to have them as part of the Clerk community and encourage you to explore their products as well as their new MCP integrations!

What's Next

This initial release focuses on Next.js support, with additional framework support coming soon. We're also working on expanded tooling and utilities to make MCP integration even more straightforward across different development environments.

Beyond server-side tooling, we're also building client-side tools to help AI applications connect with MCP endpoints more easily. If you're interested in early access for any of these features, please reach out to our support team, and we'll get you set up!

Check out our step-by-step MCP implementation guide in the documentation to get started with your first MCP-enabled endpoint.

We're excited to see what new AI-powered experiences you'll build with MCP and Clerk. If you have feedback or questions, we'd love to hear from you!

Contributor
Jeff Escalante

Share this article