Skip to content

Releases: clerk/javascript

@clerk/[email protected]

03 Mar 21:28

Choose a tag to compare

Major Changes

Minor Changes

  • Add /types subpath export to re-export types from @clerk/shared/types along with SDK-specific types. This allows importing Clerk types directly from the SDK package (e.g., import type { UserResource } from '@clerk/react/types') without needing to install @clerk/types as a separate dependency. (#7644) by @nikosdouvlis

Patch Changes

@clerk/[email protected]

03 Mar 21:27

Choose a tag to compare

Major Changes

  • Remove deprecated enableHandshake option and req.auth object-access pattern. (#7926) by @wobsoriano

    enableHandshake removed

    This option had no effect and was previously deprecated. Remove it from your clerkMiddleware call:

    // Before
    app.use(clerkMiddleware({ enableHandshake: false }));
    
    // After
    app.use(clerkMiddleware());

    req.auth must now be called as a function

    Accessing req.auth as a plain object (legacy clerk-sdk-node style) no longer works. Use getAuth() instead:

    // Before
    const { userId } = req.auth;
    
    // After
    const { userId } = getAuth(req);
  • Require Node.js 20.9.0 in all packages (#7262) by @jacekradko

  • Remove clerkJSUrl, clerkJSVersion, clerkUIUrl, and clerkUIVersion props from all SDKs. To pin a specific version of @clerk/clerk-js, import the Clerk constructor from @clerk/clerk-js and pass it to ClerkProvider via the Clerk prop. To pin a specific version of @clerk/ui, import ui from @clerk/ui and pass it via the ui prop. This bundles the modules directly with your application instead of loading them from the CDN. (#7879) by @jacekradko

Minor Changes

  • Add Frontend API proxy support via frontendApiProxy option in clerkMiddleware (#7602) by @brkalow

  • Add /types subpath export to re-export types from @clerk/shared/types along with SDK-specific types. This allows importing Clerk types directly from the SDK package (e.g., import type { UserResource } from '@clerk/react/types') without needing to install @clerk/types as a separate dependency. (#7644) by @nikosdouvlis

Patch Changes

Read more

@clerk/[email protected]

03 Mar 21:28

Choose a tag to compare

Major Changes

  • Align experimental/unstable prefixes to use consistent naming: (#7361) by @brkalow

    • Renamed all __unstable_* methods to __internal_* (for internal APIs)
    • Renamed all experimental__* and experimental_* methods to __experimental_* (for beta features)
    • Removed deprecated billing-related props (__unstable_manageBillingUrl, __unstable_manageBillingLabel, __unstable_manageBillingMembersLimit) and experimental__forceOauthFirst
  • Move useSignInWithApple and useSignInWithGoogle to dedicated entry points to avoid bundling optional dependencies. (#7737) by @chriscanin

    Breaking Change: Import paths have changed:

    // Before
    import { useSignInWithApple } from '@clerk/expo';
    import { useSignInWithGoogle } from '@clerk/expo';
    
    // After
    import { useSignInWithApple } from '@clerk/expo/apple';
    import { useSignInWithGoogle } from '@clerk/expo/google';

    This change prevents expo-crypto and expo-apple-authentication from being bundled when not using native sign-in hooks.

  • Refactor React SDK hooks to subscribe to auth state via useSyncExternalStore. This is a mostly internal refactor to unlock future improvements, but includes a few breaking changes and fixes. (#7411) by @Ephem

    Breaking changes:

    • Removes ability to pass in initialAuthState to useAuth
      • This was added for internal use and is no longer needed
      • Instead pass in initialState to the <ClerkProvider>, or dynamic if using the Next package
      • See your specific SDK documentation for more information on Server Rendering

    Fixes:

    • A bug where useAuth would sometimes briefly return the initialState rather than undefined
      • This could in certain situations incorrectly lead to a brief user: null on the first page after signing in, indicating a signed out state
    • Hydration mismatches in certain rare scenarios where subtrees would suspend and hydrate only after clerk-js had loaded fully
  • The publishableKey prop is now required in ClerkProvider. Previously, the prop was optional and would fall back to EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY or CLERK_PUBLISHABLE_KEY environment variables. (#7655) by @chriscanin

    Environment variables inside node_modules are not inlined during production builds in React Native/Expo, which could cause apps to crash in production when the publishable key is undefined.

    You must now explicitly pass the publishableKey prop to ClerkProvider:

    const publishableKey = process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY!;
    
    <ClerkProvider publishableKey={publishableKey}>{/* Your app */}</ClerkProvider>;
  • Require Node.js 20.9.0 in all packages (#7262) by @jacekradko

  • Removed legacy subpath export mappings in favor of modern package.json exports field configuration. Previously, these packages used a workaround to support subpath imports (e.g., @clerk/shared/react, @clerk/expo/web). All public APIs remain available through the main package entry points. (#7925) by @jacekradko

  • Drop support for Expo 50, 51 and 52 with updated peer dependency requirements: (#7016) by @nikosdouvlis

    @clerk/expo

    • Added new peer dependency: expo: >=53 <55
      • The core expo package is now explicitly required as a peer dependency
      • This ensures compatibility with the Expo SDK version range that supports the features used by Clerk

    @clerk/expo-passkeys

    • Updated peer dependency: expo: >=53 <55 (previously >=50 <55)
      • Minimum Expo version increased from 50 to 53
      • This aligns with the main @clerk/expo package requirements
  • Introduce <Show when={...}> as the cross-framework authorization control component and remove <Protect>, <SignedIn>, and <SignedOut> in favor of <Show>. (#7373) by @jacekradko

  • Remove deprecated Clerk export in favor of getClerkInstance(). (#7519) by @wobsoriano

    - import { Clerk } from '@clerk/clerk-expo';
    + import { getClerkInstance } from '@clerk/expo';
    
    - const token = await Clerk.session?.getToken();
    + const token = await getClerkInstance().session?.getToken();

    If you need to create the instance before ClerkProvider renders, pass the publishableKey:

    import { ClerkProvider, getClerkInstance } from '@clerk/expo';
    
    const clerkInstance = getClerkInstance({ publishableKey: 'pk_xxx' });
    
    // Use the instance outside of React
    const token = await clerkInstance?.session?.getToken();
    fetch('https://example.com/api', { headers: { Authorization: `Bearer ${token}` } });

    [!NOTE]

    • Calling getClerkInstance() with different publishable keys will create a new Clerk instance.
    • If getClerkInstance is called without a publishable key, and ClerkProvider has not rendered yet, an error will be thrown.
  • Rename package to @clerk/expo. (#6941) by @dstaley

Minor Changes

  • Add native Google Sign-In support for iOS and Android using built-in native modules. (#7208) by @chriscanin

  • Remove clerkJSVariant option and headless bundle. Use prefetchUI={false} instead. (#7629) by @jacekradko

  • Add /types subpath export to re-export types from @clerk/shared/types along with SDK-specific types. This allows importing Clerk types directly from the SDK package (e.g., import type { UserResource } from '@clerk/react/types') without needing to install @clerk/types as a separate dependency. (#7644) by @nikosdouvlis

  • Introduce <UNSAFE_PortalProvider> component which allows you to specify a custom container for Clerk floating UI elements (popovers, modals, tooltips, etc.) that use portals. Only Clerk components within the provider will be affected, components outside the provider will continue to use the default document.body for portals. (#7310) by @alexcarpenter

    This is particularly useful when using Clerk components inside external UI libraries like Radix Dialog or React Aria Components, where portaled elements need to render within the dialog's container to remain interact-able.

    'use client';
    
    import { useRef } from 'react';
    import * as Dialog from '@radix-ui/react-dialog';
    import { UNSAFE_PortalProvider, UserButton } from '@clerk/nextjs';
    
    export function UserDialog() {
      const containerRef = useRef<HTMLDivElement>(null);
    
      return (
        <Dialog.Root>
          <Dialog.Trigger>Open Dialog</Dialog.Trigger>
          <Dialog.Portal>
            <Dialog.Overlay />
            <Dialog.Content ref={containerRef}>
              <UNSAFE_PortalProvider getContainer={() => containerRef.current}>
                <UserButton />
              </UNSAFE_PortalProvider>
            </Dialog.Content>
          </Dialog.Portal>
        </Dialog.Root>
      );
    }

Patch Changes

Read more

@clerk/[email protected]

03 Mar 21:28

Choose a tag to compare

Major Changes

  • Drop support for Expo 50, 51 and 52 with updated peer dependency requirements: (#7016) by @nikosdouvlis

    @clerk/expo

    • Added new peer dependency: expo: >=53 <55
      • The core expo package is now explicitly required as a peer dependency
      • This ensures compatibility with the Expo SDK version range that supports the features used by Clerk

    @clerk/expo-passkeys

    • Updated peer dependency: expo: >=53 <55 (previously >=50 <55)
      • Minimum Expo version increased from 50 to 53
      • This aligns with the main @clerk/expo package requirements

Patch Changes

@clerk/[email protected]

03 Mar 21:28

Choose a tag to compare

Minor Changes

Patch Changes

  • Replace globby dependency with tinyglobby for smaller bundle size and faster installation (#7415) by @alexcarpenter

@clerk/[email protected]

03 Mar 21:28

Choose a tag to compare

Major Changes

  • Align experimental/unstable prefixes to use consistent naming: (#7361) by @brkalow

    • Renamed all __unstable_* methods to __internal_* (for internal APIs)
    • Renamed all experimental__* and experimental_* methods to __experimental_* (for beta features)
    • Removed deprecated billing-related props (__unstable_manageBillingUrl, __unstable_manageBillingLabel, __unstable_manageBillingMembersLimit) and experimental__forceOauthFirst
  • Renamed unstable methods to internal: (#7925) by @jacekradko

    • __unstable__environment__internal_environment
    • __unstable__updateProps__internal_updateProps
    • __unstable__setEnvironment__internal_setEnvironment
    • __unstable__onBeforeRequest__internal_onBeforeRequest
    • __unstable__onAfterResponse__internal_onAfterResponse
    • __unstable__onBeforeSetActive__internal_onBeforeSetActive (window global)
    • __unstable__onAfterSetActive__internal_onAfterSetActive (window global)
  • Add proactive session token refresh. Tokens are now automatically refreshed in the background before they expire, reducing latency for API calls near token expiration. (#7317) by @jacekradko

  • Updated returned values of Clerk.checkout() and useCheckout. (#7232) by @panteliselef

    Vanilla JS

    // Before
    const { getState, subscribe, confirm, start, clear, finalize } = Clerk.checkout({
      planId: 'xxx',
      planPeriod: 'annual',
    });
    getState().isStarting;
    getState().isConfirming;
    getState().error;
    getState().checkout;
    getState().fetchStatus;
    getState().status;
    
    // After
    const { checkout, errors, fetchStatus } = Clerk.checkout({ planId: 'xxx', planPeriod: 'annual' });
    checkout.plan; // null or defined based on `checkout.status`
    checkout.status;
    checkout.start;
    checkout.confirm;

    React

    // Before
    const { id, plan, status, start, confirm, paymentSource } = useCheckout({ planId: 'xxx', planPeriod: 'annual' });
    
    // After
    const { checkout, errors, fetchStatus } = usecCheckout({ planId: 'xxx', planPeriod: 'annual' });
    checkout.plan; // null or defined based on `checkout.status`
    checkout.status;
    checkout.start;
    checkout.confirm;
  • Remove deprecated saml property from UserSettings in favor of enterpriseSSO (#7063) by @LauraBeatris

  • Remove deprecated samlAccount in favor of enterpriseAccount (#7258) by @LauraBeatris

  • Remove clerkJSVariant option and headless bundle. Use prefetchUI={false} instead. (#7629) by @jacekradko

  • Require Node.js 20.9.0 in all packages (#7262) by @jacekradko

  • Remove all previously deprecated UI props across the Next.js, React and clerk-js SDKs. The legacy afterSign(In|Up)Url/redirectUrl props, UserButton sign-out overrides, organization hideSlug flags, OrganizationSwitcher's afterSwitchOrganizationUrl, Client.activeSessions, setActive({ beforeEmit }), and the ClerkMiddlewareAuthObject type alias are no longer exported. Components now rely solely on the new redirect options and server-side configuration. (#7243) by @jacekradko

  • Remove deprecated saml strategy in favor of enterprise_sso (#7326) by @LauraBeatris

  • getToken() now throws ClerkOfflineError instead of returning null when the client is offline. (#7598) by @bratsos

    This makes it explicit that a token fetch failure was due to network conditions, not authentication state. Previously, returning null could be misinterpreted as "user is signed out," potentially causing the cached token to be cleared.

    To handle this change, catch ClerkOfflineError from getToken() calls:

    import { ClerkOfflineError } from '@clerk/react/errors';
    
    try {
      const token = await session.getToken();
    } catch (error) {
      if (ClerkOfflineError.is(error)) {
        // Handle offline scenario - show offline UI, retry later, etc.
      }
      throw error;
    }

Minor Changes

  • Add support for email link based verification to SignUpFuture (#7745) by @dstaley

  • Surface organization creation defaults with prefilled form fields and advisory warnings (#7488) by @LauraBeatris

  • Reuse SignIn and SignUp instances on Client when processing Client response JSON. (#7803) by @dstaley

  • addListener now takes a skipInitialEmit option that can be used to avoid emitting immediately after subscribing. (#7925) by @jacekradko

  • UI components are now provided by the new @clerk/ui package, loaded automatically from the Clerk CDN. (#7925) by @jacekradko

  • Don't display impersonation overlay for agents (#7933) by @tmilewski

  • Hide the "Remove" action from the last available 2nd factor strategy when MFA is required (#7729) by @octoper

  • Renames mountTaskSetupMfa and unmountTaskSetupMfa to mountTaskSetupMFA and unmountTaskSetupMFA respectively (#7859) by @octoper

  • Add unsafe_disableDevelopmentModeConsoleWarning option to disable the development mode warning that's emitted to the console when Clerk is first loaded. (#7505) by @dstaley

  • Refactor React SDK hooks to subscribe to auth state via useSyncExternalStore. This is a mostly internal refactor to unlock future improvements, but includes a few breaking changes and fixes. (#7411) by @Ephem

    Breaking changes:

    • Removes ability to pass in initialAuthState to useAuth
      • This was added for internal use and is no longer needed
      • Instead pass in initialState to the <ClerkProvider>, or dynamic if using the Next package
      • See your specific SDK documentation for more information on Server Rendering

    Fixes:

    • A bug where useAuth would sometimes briefly return the initialState rather than undefined
      • This could in certain situations incorrectly lead to a brief user: null on the first page after signing in, indicating a signed out state
    • Hydration mismatches in certain rare scenarios where subtrees would suspend and hydrate only after clerk-js had loaded fully
  • Add support for email code MFA to SignInFuture (#7594) by @dstaley

  • Introducing setup_mfa session task (#7626) by @octoper

  • Add additional verification fields to SignUpFuture. (#7666) by @dstaley

  • Add support for resetting a password via phone code. (#7824) by @dstaley

  • Disable role selection in OrganizationProfile during role set migration (#7534) by @LauraBeatris

  • Add Safari ITP (Intelligent Tracking Prevention) cookie refresh support. (#7623) by @nikosdouvlis

    Safari's ITP limits cookies set via JavaScript to 7 days. When a session cookie is close to expiring (within 8 days), Clerk now automatically routes navigations through a /v1/client/touch endpoint to refresh the cookie via a full-page navigation, bypassing the 7-day cap.

    For developers using a custom navigate callback in setActive(), a new decorateUrl function is passed to the callback. Use it to wrap your destination URL:

    await clerk.setActive({
      session: newSession,
      navigate: ({ decorateUrl }) => {
        const url = decorateUrl('/dashboard');
        window.location.href = url;
      },
    });

    The decorateUrl function returns the original URL unchanged when the Safari ITP fix is not needed, so it's safe to always use it.

  • Add satelliteAutoSync option to optimize satellite app handshake behavior (#7597) by @nikosdouvlis

    Satellite apps currently trigger a handshake redirect on every first page load, even when no cookies exist. This creates unnecessary redirec...

Read more

@clerk/[email protected]

03 Mar 21:28

Choose a tag to compare

Major Changes

  • Align experimental/unstable prefixes to use consistent naming: (#7361) by @brkalow

    • Renamed all __unstable_* methods to __internal_* (for internal APIs)
    • Renamed all experimental__* and experimental_* methods to __experimental_* (for beta features)
    • Removed deprecated billing-related props (__unstable_manageBillingUrl, __unstable_manageBillingLabel, __unstable_manageBillingMembersLimit) and experimental__forceOauthFirst
  • Renamed __unstable__createClerkClient to createClerkClient (exported from @clerk/chrome-extension/background). (#7925) by @jacekradko

  • Refactor React SDK hooks to subscribe to auth state via useSyncExternalStore. This is a mostly internal refactor to unlock future improvements, but includes a few breaking changes and fixes. (#7411) by @Ephem

    Breaking changes:

    • Removes ability to pass in initialAuthState to useAuth
      • This was added for internal use and is no longer needed
      • Instead pass in initialState to the <ClerkProvider>, or dynamic if using the Next package
      • See your specific SDK documentation for more information on Server Rendering

    Fixes:

    • A bug where useAuth would sometimes briefly return the initialState rather than undefined
      • This could in certain situations incorrectly lead to a brief user: null on the first page after signing in, indicating a signed out state
    • Hydration mismatches in certain rare scenarios where subtrees would suspend and hydrate only after clerk-js had loaded fully
  • Require Node.js 20.9.0 in all packages (#7262) by @jacekradko

  • Introduce <Show when={...}> as the cross-framework authorization control component and remove <Protect>, <SignedIn>, and <SignedOut> in favor of <Show>. (#7373) by @jacekradko

Minor Changes

  • Remove clerkJSVariant option and headless bundle. Use prefetchUI={false} instead. (#7629) by @jacekradko

  • Add ui prop to ClerkProvider for passing @clerk/ui (#7664) by @jacekradko

  • Export useOrganizationCreationDefaults hook to fetch suggested organization name and logo from default naming rules (#7694) by @LauraBeatris

  • Add /types subpath export to re-export types from @clerk/shared/types along with SDK-specific types. This allows importing Clerk types directly from the SDK package (e.g., import type { UserResource } from '@clerk/react/types') without needing to install @clerk/types as a separate dependency. (#7644) by @nikosdouvlis

  • Add HandleSSOCallback component which handles the SSO callback during custom flows, including support for sign-in-or-up. (#7678) by @dstaley

  • Added new createClerkClient() export from @clerk/chrome-extension/client (#7935) by @royanger

    import { createClerkClient } from '@clerk/chrome-extension/client';
    
    const publishableKey = process.env.CLERK_PUBLISHABLE_KEY;
    // Use createClerkClient in a popup or side panel
    const clerk = createClerkClient({ publishableKey });
    
    // Use createClerkClient in a background service worker
    const clerk = await createClerkClient({ publishableKey: 'pk_...', background: true });

    createClerkClient() from @clerk/chrome-extension/background is deprecated.

Patch Changes

Read more

@clerk/[email protected]

03 Mar 21:28

Choose a tag to compare

Major Changes

  • Remove deprecated verify methods in favor of verify(). (#7927) by @wobsoriano

    apiKeys.verifySecret() removed

    // Before
    await clerkClient.apiKeys.verifySecret(secret);
    
    // After
    await clerkClient.apiKeys.verify(secret);

    idpOAuthAccessToken.verifyAccessToken() removed

    // Before
    await clerkClient.idpOAuthAccessToken.verifyAccessToken(accessToken);
    
    // After
    await clerkClient.idpOAuthAccessToken.verify(accessToken);

    m2m.verifyToken() removed

    // Before
    await clerkClient.m2m.verifyToken(params);
    
    // After
    await clerkClient.m2m.verify(params);
  • Update engines config to require node@20 or higher (#6931) by @jacekradko

  • Remove deprecated samlAccount in favor of enterpriseAccount (#7258) by @LauraBeatris

Minor Changes

  • Add support for Agent Tasks API endpoint which allows developers to create agent tasks that can be used to act on behalf of users through automated flows. (#7783) by @tmilewski

  • Add Frontend API proxy support via frontendApiProxy option in clerkMiddleware (#7602) by @brkalow

  • Add satelliteAutoSync option to optimize satellite app handshake behavior (#7597) by @nikosdouvlis

    Satellite apps currently trigger a handshake redirect on every first page load, even when no cookies exist. This creates unnecessary redirects to the primary domain for apps where most users aren't authenticated.

    New option: satelliteAutoSync (default: false)

    • When false (default): Skip automatic handshake if no session cookies exist, only trigger after explicit sign-in action
    • When true: Satellite apps automatically trigger handshake on first load (previous behavior)

    New query parameter: __clerk_sync

    • __clerk_sync=1 (NeedsSync): Triggers handshake after returning from primary sign-in
    • __clerk_sync=2 (Completed): Prevents re-sync loop after handshake completes

    Backwards compatible: Still reads legacy __clerk_synced=true parameter.

    SSR redirect fix: Server-side redirects (e.g., redirectToSignIn() from middleware) now correctly add __clerk_sync=1 to the return URL for satellite apps. This ensures the handshake is triggered when the user returns from sign-in on the primary domain.

    CSR redirect fix: Client-side redirects now add __clerk_sync=1 to all redirect URL variants (forceRedirectUrl, fallbackRedirectUrl) for satellite apps, not just the default redirectUrl.

    Usage

    SSR (Next.js Middleware)

    import { clerkMiddleware } from '@clerk/nextjs/server';
    
    export default clerkMiddleware({
      isSatellite: true,
      domain: 'satellite.example.com',
      signInUrl: 'https://primary.example.com/sign-in',
      // Set to true to automatically sync auth state on first load
      satelliteAutoSync: true,
    });

    SSR (TanStack Start)

    import { clerkMiddleware } from '@clerk/tanstack-react-start/server';
    
    export default clerkMiddleware({
      isSatellite: true,
      domain: 'satellite.example.com',
      signInUrl: 'https://primary.example.com/sign-in',
      // Set to true to automatically sync auth state on first load
      satelliteAutoSync: true,
    });

    CSR (ClerkProvider)

    <ClerkProvider
      publishableKey='pk_...'
      isSatellite={true}
      domain='satellite.example.com'
      signInUrl='https://primary.example.com/sign-in'
      // Set to true to automatically sync auth state on first load
      satelliteAutoSync={true}
    >
      {children}
    </ClerkProvider>

    SSR (TanStack Start with callback)

    import { clerkMiddleware } from '@clerk/tanstack-react-start/server';
    
    // Options callback - receives context object, returns options
    export default clerkMiddleware(({ url }) => ({
      isSatellite: true,
      domain: 'satellite.example.com',
      signInUrl: 'https://primary.example.com/sign-in',
      satelliteAutoSync: url.pathname.startsWith('/dashboard'),
    }));

    Migration Guide

    Behavior change: satelliteAutoSync defaults to false

    Previously, satellite apps would automatically trigger a handshake redirect on every first page load to sync authentication state with the primary domain—even when no session cookies existed. This caused unnecessary redirects to the primary domain for users who weren't authenticated.

    The new default (satelliteAutoSync: false) provides a better experience for end users. Performance-wise, the satellite app can be shown immediately without attempting to sync state first, which is the right behavior for most use cases.

    To preserve the previous behavior where visiting a satellite while already signed in on the primary domain automatically syncs your session, set satelliteAutoSync: true:

    export default clerkMiddleware({
      isSatellite: true,
      domain: 'satellite.example.com',
      signInUrl: 'https://primary.example.com/sign-in',
      satelliteAutoSync: true, // Opt-in to automatic sync on first load
    });

    TanStack Start: Function props to options callback

    The clerkMiddleware function no longer accepts individual props as functions. If you were using the function form for props like domain, proxyUrl, or isSatellite, migrate to the options callback pattern.

    Before (prop function form - no longer supported):

    import { clerkMiddleware } from '@clerk/tanstack-react-start/server';
    
    export default clerkMiddleware({
      isSatellite: true,
      // ❌ Function form for individual props no longer works
      domain: url => url.hostname,
    });

    After (options callback form):

    import { clerkMiddleware } from '@clerk/tanstack-react-start/server';
    
    // ✅ Wrap entire options in a callback function
    export default clerkMiddleware(({ url }) => ({
      isSatellite: true,
      domain: url.hostname,
    }));

    The callback receives a context object with the url property (a URL instance) and can return options synchronously or as a Promise for async configuration.

Patch Changes

  • Warn when a cookie-based session token is missing the azp claim instead of rejecting the token. This prepares consumers for a future version where the azp claim will be required. (#7929) by @jacekradko

  • Dropping the __experimental_ prefix from setPasswordCompromised and unsetPasswordCompromised and marking them as stable (#7504) by @octoper

  • Added date filter parameters to user list endpoint (#7793) by @wobsoriano

  • Fixes an issue with host header parsing that would cause Clerk to throw an exception when receiving malformed host values. (#7370) by @brkalow

  • Improve token type validation in authentication requests (#7765) by @wobsoriano

  • Allow null for period_end in BillingSubscriptionItemWebhookEventJSON (#7699) by @jacekradko

  • fix: Update getAuthData to use isMachineToken (#7755) by @jeremy-clerk

  • Allow usage of machine secret key when listing M2M tokens: (#7968) by @wobsoriano

    const clerkClient = createClerkClient();
    
    const m2mToken = await clerkClient.m2m.list({
      machineSecretKey: 'ak_xxxxx',
      subject: machineId,
    });
  • Add missing fields to CommercePlan type. (#7707) by @dstaley

  • Updated dependencies [0a9cce3, e35960f, c9f0d77, 1bd1747, 6a2ff9e, d2cee35, 0a9cce3, a374c18, 466d642, 5ef4a77, af85739, 10b5bea, [a05d130](https://github....

Read more

@clerk/[email protected]

03 Mar 21:27

Choose a tag to compare

Major Changes

  • Align experimental/unstable prefixes to use consistent naming: (#7361) by @brkalow

    • Renamed all __unstable_* methods to __internal_* (for internal APIs)
    • Renamed all experimental__* and experimental_* methods to __experimental_* (for beta features)
    • Removed deprecated billing-related props (__unstable_manageBillingUrl, __unstable_manageBillingLabel, __unstable_manageBillingMembersLimit) and experimental__forceOauthFirst
  • Require Node.js 20.9.0 in all packages (#7262) by @jacekradko

  • Remove deprecated as prop from unstyled button components (SignInButton, SignUpButton, SignOutButton, CheckoutButton, PlanDetailsButton, SubscriptionDetailsButton). Use the asChild prop with a custom element in the default slot instead. (#7839) by @wobsoriano

    Before:

    <SignInButton
      as='a'
      href='/sign-in'
    >
      Sign in
    </SignInButton>

    After:

    <SignInButton asChild>
      <a href='/sign-in'>Sign in</a>
    </SignInButton>
  • Remove clerkJSUrl, clerkJSVersion, clerkUIUrl, and clerkUIVersion props from all SDKs. To pin a specific version of @clerk/clerk-js, import the Clerk constructor from @clerk/clerk-js and pass it to ClerkProvider via the Clerk prop. To pin a specific version of @clerk/ui, import ui from @clerk/ui and pass it via the ui prop. This bundles the modules directly with your application instead of loading them from the CDN. (#7879) by @jacekradko

  • Introduce <Show when={...}> as the cross-framework authorization control component and remove <Protect>, <SignedIn>, and <SignedOut> in favor of <Show>. (#7373) by @jacekradko

  • Changed environment variable resolution order in getContextEnvVar() to prefer process.env over import.meta.env. Runtime environment variables (e.g., set in the Node.js adapter) now take precedence over build-time values statically replaced by Vite. This ensures that environment variables set at runtime behave as expected when deploying with the Astro Node adapter or similar runtime environments. (#7889) by @alexcarpenter

Minor Changes

  • Remove clerkJSVariant option and headless bundle. Use prefetchUI={false} instead. (#7629) by @jacekradko

  • Introduce Keyless quickstart for Astro. This allows the Clerk SDK to be used without having to sign up and paste your keys manually. (#7812) by @wobsoriano

  • Add ui prop to ClerkProvider for passing @clerk/ui (#7664) by @jacekradko

  • Add standalone getToken() function for retrieving session tokens outside of framework component trees. (#7325) by @bratsos

    This function is safe to call from anywhere in the browser, such as API interceptors, data fetching layers (e.g., React Query, SWR), or vanilla JavaScript code. It automatically waits for Clerk to initialize before returning the token.

    import { getToken } from '@clerk/nextjs'; // or any framework package

    // Example: Axios interceptor
    axios.interceptors.request.use(async (config) => {
    const token = await getToken();
    if (token) {
    config.headers.Authorization = Bearer ${token};
    }
    return config;
    });

  • Add /types subpath export to re-export types from @clerk/shared/types along with SDK-specific types. This allows importing Clerk types directly from the SDK package (e.g., import type { UserResource } from '@clerk/react/types') without needing to install @clerk/types as a separate dependency. (#7644) by @nikosdouvlis

  • Introduce <UNSAFE_PortalProvider> component which allows you to specify a custom container for Clerk floating UI elements (popovers, modals, tooltips, etc.) that use portals. Only Clerk components within the provider will be affected, components outside the provider will continue to use the default document.body for portals. (#7310) by @alexcarpenter

    This is particularly useful when using Clerk components inside external UI libraries like Radix Dialog or React Aria Components, where portaled elements need to render within the dialog's container to remain interact-able.

    'use client';
    
    import { useRef } from 'react';
    import * as Dialog from '@radix-ui/react-dialog';
    import { UNSAFE_PortalProvider, UserButton } from '@clerk/nextjs';
    
    export function UserDialog() {
      const containerRef = useRef<HTMLDivElement>(null);
    
      return (
        <Dialog.Root>
          <Dialog.Trigger>Open Dialog</Dialog.Trigger>
          <Dialog.Portal>
            <Dialog.Overlay />
            <Dialog.Content ref={containerRef}>
              <UNSAFE_PortalProvider getContainer={() => containerRef.current}>
                <UserButton />
              </UNSAFE_PortalProvider>
            </Dialog.Content>
          </Dialog.Portal>
        </Dialog.Root>
      );
    }

Patch Changes

  • Rename dev browser APIs to remove JWT terminology. The dev browser identifier is now a generic ID, so internal naming has been updated to reflect this. No runtime behavior changes. (#7930) by @brkalow

  • Wire clerkUIVersion option through all framework packages (#7740) by @nikosdouvlis

  • Fix compatibility with Astro v6 Cloudflare adapter by using cloudflare:workers env when locals.runtime.env is unavailable (#7890) by @alexcarpenter

  • Add satelliteAutoSync option to optimize satellite app handshake behavior (#7597) by @nikosdouvlis

    Satellite apps currently trigger a handshake redirect on every first page load, even when no cookies exist. This creates unnecessary redirects to the primary domain for apps where most users aren't authenticated.

    New option: satelliteAutoSync (default: false)

    • When false (default): Skip automatic handshake if no session cookies exist, only trigger after explicit sign-in action
    • When true: Satellite apps automatically trigger handshake on first load (previous behavior)

    New query parameter: __clerk_sync

    • __clerk_sync=1 (NeedsSync): Triggers handshake after returning from primary sign-in
    • __clerk_sync=2 (Completed): Prevents re-sync loop after handshake completes

    Backwards compatible: Still reads legacy __clerk_synced=true parameter.

    SSR redirect fix: Server-side redirects (e.g., redirectToSignIn() from middleware) now correctly add __clerk_sync=1 to the return URL for satellite apps. This ensures the handshake is triggered when the user returns from sign-in on the primary domain.

    CSR redirect fix: Client-side redirects now add __clerk_sync=1 to all redirect URL variants (forceRedirectUrl, fallbackRedirectUrl) for satellite apps, not just the default redirectUrl.

    Usage

    SSR (Next.js Middleware)

    import { clerkMiddleware } from '@clerk/nextjs/server';
    
    export default clerkMiddleware({
      isSatellite: true,
      domain: 'satellite.example.com',
      signInUrl: 'https://primary.example.com/sign-in',
      // Set to true to automatically sync auth state on first load
      satelliteAutoSync: true,
    });

    SSR (TanStack Start)

    import { clerkMiddleware } from '@clerk/tanstack-react-start/server';
    
    export default clerkMiddleware({
      isSatellite: true,
      domain: 'satellite.example.com',
      signInUrl: 'https://primary.example.com/sign-in',
      // Set to true to automatically sync auth state on first load
      satelliteAutoSync: true,
    });

    CSR (ClerkProvider)

    <ClerkProvider
      publishableKey='pk_...'
      isSatellite={true}
      domain='satellite.example.com'
      signInUrl='https://primary.example.com/sign-in'
      // Set to true to automatically sync auth state on first load
      satelliteAutoSync={true}
    >
      {children}
    </ClerkProvider>

    SSR (TanStack Start with callback)

    import { clerkMiddleware } from '@clerk/tanstack-react-start/server';
    
    // Options callback - receives context object, returns options
    export default clerkMiddleware(({ url }) => ({
      isSatellite: true,
      domain: 'satellite.example.com',
      signInUrl: 'https://primary.example.com/sign-in',
      satelliteAutoSync: url.pathname.startsWith('/dashboard'),
    }));

    Migration Guide

    Behavior change: satelliteAutoSync defaults to false

    Previously, satellite apps would automatically trigger a handshake redirect on every fir...

Read more

@clerk/[email protected]

03 Mar 21:28

Choose a tag to compare