diff --git a/apps/sim/app/(auth)/login/login-form.tsx b/apps/sim/app/(auth)/login/login-form.tsx index 22ba678a76..3013a4e284 100644 --- a/apps/sim/app/(auth)/login/login-form.tsx +++ b/apps/sim/app/(auth)/login/login-form.tsx @@ -1,7 +1,6 @@ 'use client' -import { useMemo, useRef, useState } from 'react' -import { Turnstile, type TurnstileInstance } from '@marsidev/react-turnstile' +import { useRef, useState } from 'react' import { createLogger } from '@sim/logger' import { Eye, EyeOff } from 'lucide-react' import Link from 'next/link' @@ -88,8 +87,6 @@ export default function LoginPage({ const [passwordErrors, setPasswordErrors] = useState([]) const [showValidationError, setShowValidationError] = useState(false) const [formError, setFormError] = useState(null) - const turnstileRef = useRef(null) - const turnstileSiteKey = useMemo(() => getEnv('NEXT_PUBLIC_TURNSTILE_SITE_KEY'), []) const buttonClass = useBrandedButtonClass() const callbackUrlParam = searchParams?.get('callbackUrl') @@ -169,20 +166,6 @@ export default function LoginPage({ const safeCallbackUrl = callbackUrl let errorHandled = false - // Execute Turnstile challenge on submit and get a fresh token - let token: string | undefined - if (turnstileSiteKey && turnstileRef.current) { - try { - turnstileRef.current.reset() - turnstileRef.current.execute() - token = await turnstileRef.current.getResponsePromise(15_000) - } catch { - setFormError('Captcha verification failed. Please try again.') - setIsLoading(false) - return - } - } - setFormError(null) const result = await client.signIn.email( { @@ -191,11 +174,6 @@ export default function LoginPage({ callbackURL: safeCallbackUrl, }, { - fetchOptions: { - headers: { - ...(token ? { 'x-captcha-response': token } : {}), - }, - }, onError: (ctx) => { logger.error('Login error:', ctx.error) @@ -464,16 +442,6 @@ export default function LoginPage({ - {turnstileSiteKey && ( -
- -
- )} - {resetSuccessMessage && (

{resetSuccessMessage}

diff --git a/apps/sim/app/(auth)/signup/signup-form.tsx b/apps/sim/app/(auth)/signup/signup-form.tsx index 4a9ab24aa2..1054259a41 100644 --- a/apps/sim/app/(auth)/signup/signup-form.tsx +++ b/apps/sim/app/(auth)/signup/signup-form.tsx @@ -93,6 +93,8 @@ function SignupFormContent({ const [showEmailValidationError, setShowEmailValidationError] = useState(false) const [formError, setFormError] = useState(null) const turnstileRef = useRef(null) + const captchaResolveRef = useRef<((token: string) => void) | null>(null) + const captchaRejectRef = useRef<((reason: Error) => void) | null>(null) const turnstileSiteKey = useMemo(() => getEnv('NEXT_PUBLIC_TURNSTILE_SITE_KEY'), []) const buttonClass = useBrandedButtonClass() @@ -249,17 +251,30 @@ function SignupFormContent({ const sanitizedName = trimmedName - // Execute Turnstile challenge on submit and get a fresh token let token: string | undefined - if (turnstileSiteKey && turnstileRef.current) { + const widget = turnstileRef.current + if (turnstileSiteKey && widget) { + let timeoutId: ReturnType | undefined try { - turnstileRef.current.reset() - turnstileRef.current.execute() - token = await turnstileRef.current.getResponsePromise(15_000) + widget.reset() + token = await Promise.race([ + new Promise((resolve, reject) => { + captchaResolveRef.current = resolve + captchaRejectRef.current = reject + widget.execute() + }), + new Promise((_, reject) => { + timeoutId = setTimeout(() => reject(new Error('Captcha timed out')), 15_000) + }), + ]) } catch { setFormError('Captcha verification failed. Please try again.') setIsLoading(false) return + } finally { + clearTimeout(timeoutId) + captchaResolveRef.current = null + captchaRejectRef.current = null } } @@ -478,13 +493,14 @@ function SignupFormContent({
{turnstileSiteKey && ( -
- -
+ captchaResolveRef.current?.(token)} + onError={() => captchaRejectRef.current?.(new Error('Captcha verification failed'))} + onExpire={() => captchaRejectRef.current?.(new Error('Captcha token expired'))} + options={{ execution: 'execute' }} + /> )} {formError && ( diff --git a/apps/sim/lib/auth/auth.ts b/apps/sim/lib/auth/auth.ts index bd514245ea..166353d0eb 100644 --- a/apps/sim/lib/auth/auth.ts +++ b/apps/sim/lib/auth/auth.ts @@ -717,7 +717,7 @@ export const auth = betterAuth({ captcha({ provider: 'cloudflare-turnstile', secretKey: env.TURNSTILE_SECRET_KEY, - endpoints: ['/sign-up/email', '/sign-in/email'], + endpoints: ['/sign-up/email'], }), ] : []),