Skip to content

Commit 83d36f6

Browse files
waleedlatif1Sg312
authored andcommitted
fix(auth): remove captcha from login, fix signup captcha flow (#3753)
* fix(auth): remove captcha from login, fix signup captcha flow * fix(auth): show Turnstile widget at normal size for Managed mode challenges
1 parent c29b5be commit 83d36f6

File tree

3 files changed

+30
-46
lines changed

3 files changed

+30
-46
lines changed

apps/sim/app/(auth)/login/login-form.tsx

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use client'
22

3-
import { useMemo, useRef, useState } from 'react'
4-
import { Turnstile, type TurnstileInstance } from '@marsidev/react-turnstile'
3+
import { useRef, useState } from 'react'
54
import { createLogger } from '@sim/logger'
65
import { Eye, EyeOff } from 'lucide-react'
76
import Link from 'next/link'
@@ -88,8 +87,6 @@ export default function LoginPage({
8887
const [passwordErrors, setPasswordErrors] = useState<string[]>([])
8988
const [showValidationError, setShowValidationError] = useState(false)
9089
const [formError, setFormError] = useState<string | null>(null)
91-
const turnstileRef = useRef<TurnstileInstance>(null)
92-
const turnstileSiteKey = useMemo(() => getEnv('NEXT_PUBLIC_TURNSTILE_SITE_KEY'), [])
9390
const buttonClass = useBrandedButtonClass()
9491

9592
const callbackUrlParam = searchParams?.get('callbackUrl')
@@ -169,20 +166,6 @@ export default function LoginPage({
169166
const safeCallbackUrl = callbackUrl
170167
let errorHandled = false
171168

172-
// Execute Turnstile challenge on submit and get a fresh token
173-
let token: string | undefined
174-
if (turnstileSiteKey && turnstileRef.current) {
175-
try {
176-
turnstileRef.current.reset()
177-
turnstileRef.current.execute()
178-
token = await turnstileRef.current.getResponsePromise(15_000)
179-
} catch {
180-
setFormError('Captcha verification failed. Please try again.')
181-
setIsLoading(false)
182-
return
183-
}
184-
}
185-
186169
setFormError(null)
187170
const result = await client.signIn.email(
188171
{
@@ -191,11 +174,6 @@ export default function LoginPage({
191174
callbackURL: safeCallbackUrl,
192175
},
193176
{
194-
fetchOptions: {
195-
headers: {
196-
...(token ? { 'x-captcha-response': token } : {}),
197-
},
198-
},
199177
onError: (ctx) => {
200178
logger.error('Login error:', ctx.error)
201179

@@ -464,16 +442,6 @@ export default function LoginPage({
464442
</div>
465443
</div>
466444

467-
{turnstileSiteKey && (
468-
<div className='absolute'>
469-
<Turnstile
470-
ref={turnstileRef}
471-
siteKey={turnstileSiteKey}
472-
options={{ size: 'invisible', execution: 'execute' }}
473-
/>
474-
</div>
475-
)}
476-
477445
{resetSuccessMessage && (
478446
<div className='text-[#4CAF50] text-xs'>
479447
<p>{resetSuccessMessage}</p>

apps/sim/app/(auth)/signup/signup-form.tsx

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ function SignupFormContent({
9393
const [showEmailValidationError, setShowEmailValidationError] = useState(false)
9494
const [formError, setFormError] = useState<string | null>(null)
9595
const turnstileRef = useRef<TurnstileInstance>(null)
96+
const captchaResolveRef = useRef<((token: string) => void) | null>(null)
97+
const captchaRejectRef = useRef<((reason: Error) => void) | null>(null)
9698
const turnstileSiteKey = useMemo(() => getEnv('NEXT_PUBLIC_TURNSTILE_SITE_KEY'), [])
9799
const buttonClass = useBrandedButtonClass()
98100

@@ -249,17 +251,30 @@ function SignupFormContent({
249251

250252
const sanitizedName = trimmedName
251253

252-
// Execute Turnstile challenge on submit and get a fresh token
253254
let token: string | undefined
254-
if (turnstileSiteKey && turnstileRef.current) {
255+
const widget = turnstileRef.current
256+
if (turnstileSiteKey && widget) {
257+
let timeoutId: ReturnType<typeof setTimeout> | undefined
255258
try {
256-
turnstileRef.current.reset()
257-
turnstileRef.current.execute()
258-
token = await turnstileRef.current.getResponsePromise(15_000)
259+
widget.reset()
260+
token = await Promise.race([
261+
new Promise<string>((resolve, reject) => {
262+
captchaResolveRef.current = resolve
263+
captchaRejectRef.current = reject
264+
widget.execute()
265+
}),
266+
new Promise<string>((_, reject) => {
267+
timeoutId = setTimeout(() => reject(new Error('Captcha timed out')), 15_000)
268+
}),
269+
])
259270
} catch {
260271
setFormError('Captcha verification failed. Please try again.')
261272
setIsLoading(false)
262273
return
274+
} finally {
275+
clearTimeout(timeoutId)
276+
captchaResolveRef.current = null
277+
captchaRejectRef.current = null
263278
}
264279
}
265280

@@ -478,13 +493,14 @@ function SignupFormContent({
478493
</div>
479494

480495
{turnstileSiteKey && (
481-
<div className='absolute'>
482-
<Turnstile
483-
ref={turnstileRef}
484-
siteKey={turnstileSiteKey}
485-
options={{ size: 'invisible', execution: 'execute' }}
486-
/>
487-
</div>
496+
<Turnstile
497+
ref={turnstileRef}
498+
siteKey={turnstileSiteKey}
499+
onSuccess={(token) => captchaResolveRef.current?.(token)}
500+
onError={() => captchaRejectRef.current?.(new Error('Captcha verification failed'))}
501+
onExpire={() => captchaRejectRef.current?.(new Error('Captcha token expired'))}
502+
options={{ execution: 'execute' }}
503+
/>
488504
)}
489505

490506
{formError && (

apps/sim/lib/auth/auth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ export const auth = betterAuth({
717717
captcha({
718718
provider: 'cloudflare-turnstile',
719719
secretKey: env.TURNSTILE_SECRET_KEY,
720-
endpoints: ['/sign-up/email', '/sign-in/email'],
720+
endpoints: ['/sign-up/email'],
721721
}),
722722
]
723723
: []),

0 commit comments

Comments
 (0)