diff --git a/.changeset/rich-badgers-pump.md b/.changeset/rich-badgers-pump.md
new file mode 100644
index 0000000000..91a13ed520
--- /dev/null
+++ b/.changeset/rich-badgers-pump.md
@@ -0,0 +1,5 @@
+---
+'@clerk/elements': minor
+---
+
+Introduce support for `` and ``. This allows rendering of a CAPTCHA widget when a sign in attempt is transferred to a sign up attempt.
diff --git a/packages/elements/examples/nextjs/app/sign-in/[[...sign-in]]/page.tsx b/packages/elements/examples/nextjs/app/sign-in/[[...sign-in]]/page.tsx
index e99e7cfbc9..d428a07f6d 100644
--- a/packages/elements/examples/nextjs/app/sign-in/[[...sign-in]]/page.tsx
+++ b/packages/elements/examples/nextjs/app/sign-in/[[...sign-in]]/page.tsx
@@ -499,6 +499,7 @@ export default function SignInPage() {
Update Password
+
);
diff --git a/packages/elements/src/internals/machines/third-party/third-party.actors.ts b/packages/elements/src/internals/machines/third-party/third-party.actors.ts
index 592f273814..e80a48b2e9 100644
--- a/packages/elements/src/internals/machines/third-party/third-party.actors.ts
+++ b/packages/elements/src/internals/machines/third-party/third-party.actors.ts
@@ -78,10 +78,6 @@ export const handleRedirectCallback = fromCallback;
+
+type CaptchaElementProps = Omit<
+ React.DetailedHTMLProps, HTMLDivElement>,
+ 'id' | 'children'
+>;
+
+export type SignInCaptchaProps =
+ | ({
+ asChild: true;
+ /* Must only be a self-closing element/component */
+ children: React.ReactElement;
+ } & CaptchaElementProps)
+ | ({ asChild?: false; children?: undefined } & CaptchaElementProps);
+
+/**
+ * The `` component is used to render the Cloudflare Turnstile widget. It must be used within the `` component.
+ *
+ * If utilizing the `asChild` prop, the component must be a self-closing element or component. Any children passed to the immediate child component of will be ignored.
+ *
+ * @param {boolean} [asChild] - If true, `` will render as its child element, passing along any necessary props.
+ *
+ * @example
+ *
+ *
+ *
+ *
+ *
+ *
+ * @example
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+export const SignInCaptcha = React.forwardRef(
+ ({ asChild, children, ...rest }, forwardedRef) => {
+ const routerRef = SignInRouterCtx.useActorRef();
+ const activeState = useActiveTags(routerRef, 'step:callback');
+
+ if (!activeState) {
+ throw new ClerkElementsRuntimeError(
+ ' must be used within the component.',
+ );
+ }
+
+ const Comp = asChild ? Slot : 'div';
+
+ return (
+
+ );
+ },
+);
diff --git a/packages/elements/src/react/sign-in/sso-callback.tsx b/packages/elements/src/react/sign-in/sso-callback.tsx
new file mode 100644
index 0000000000..1bb5c62c2b
--- /dev/null
+++ b/packages/elements/src/react/sign-in/sso-callback.tsx
@@ -0,0 +1,13 @@
+import type { PropsWithChildren } from 'react';
+
+import { useActiveTags } from '~/react/hooks';
+import { SignInRouterCtx } from '~/react/sign-in/context';
+
+export type SignInSSOCallbackProps = PropsWithChildren;
+
+export function SignInSSOCallback({ children }: SignInSSOCallbackProps) {
+ const routerRef = SignInRouterCtx.useActorRef();
+ const activeState = useActiveTags(routerRef, 'step:callback');
+
+ return activeState ? children : null;
+}
diff --git a/packages/elements/src/react/sign-in/step.tsx b/packages/elements/src/react/sign-in/step.tsx
index 89a5be4f9c..9d7f70aa4a 100644
--- a/packages/elements/src/react/sign-in/step.tsx
+++ b/packages/elements/src/react/sign-in/step.tsx
@@ -6,6 +6,8 @@ import { ClerkElementsRuntimeError } from '~/internals/errors';
import { SignInChooseSession, type SignInChooseSessionProps } from './choose-session';
import { SignInChooseStrategy, type SignInChooseStrategyProps, SignInForgotPassword } from './choose-strategy';
import { SignInResetPassword, type SignInResetPasswordProps } from './reset-password';
+import type { SignInSSOCallbackProps } from './sso-callback';
+import { SignInSSOCallback } from './sso-callback';
import { SignInStart, type SignInStartProps } from './start';
import { SignInVerifications, type SignInVerificationsProps } from './verifications';
@@ -16,6 +18,7 @@ export const SIGN_IN_STEPS = {
'choose-session': 'choose-session',
'forgot-password': 'forgot-password',
'reset-password': 'reset-password',
+ 'sso-callback': 'sso-callback',
} as const;
export type TSignInStep = (typeof SIGN_IN_STEPS)[keyof typeof SIGN_IN_STEPS];
@@ -26,7 +29,8 @@ export type SignInStepProps =
| StepWithProps<'verifications', SignInVerificationsProps>
| StepWithProps<'choose-strategy' | 'forgot-password', SignInChooseStrategyProps>
| StepWithProps<'reset-password', SignInResetPasswordProps>
- | StepWithProps<'choose-session', SignInChooseSessionProps>;
+ | StepWithProps<'choose-session', SignInChooseSessionProps>
+ | StepWithProps<'sso-callback', SignInSSOCallbackProps>;
/**
* Render different steps of the sign-in flow. Initially the `'start'` step is rendered. Once a sign-in attempt has been created, `'verifications'` will be displayed. If during that verification step the user decides to choose a different method of signing in or verifying, the `'choose-strategy'` step will be displayed.
@@ -63,6 +67,8 @@ export function SignInStep(props: SignInStepProps) {
return ;
case SIGN_IN_STEPS['choose-session']:
return ;
+ case SIGN_IN_STEPS['sso-callback']:
+ return ;
default:
throw new ClerkElementsRuntimeError(`Invalid step name. Use: ${Object.keys(SIGN_IN_STEPS).join(',')}.`);
}