Skip to content

fix(auth): remove captcha from login, fix signup captcha flow#3753

Merged
waleedlatif1 merged 2 commits intostagingfrom
fix/hcap
Mar 25, 2026
Merged

fix(auth): remove captcha from login, fix signup captcha flow#3753
waleedlatif1 merged 2 commits intostagingfrom
fix/hcap

Conversation

@waleedlatif1
Copy link
Collaborator

Summary

  • Remove Turnstile captcha from login entirely — captcha was blocking legitimate users with a 15s silent timeout due to Cloudflare's invisible widget silently erroring with no fallback. Login has credential verification; it doesn't need captcha.
  • Remove /sign-in/email from server-side captcha endpoints
  • Fix signup captcha flow: replace broken getResponsePromise() approach with canonical onSuccess/onError/onExpire callback pattern wired to resolve/reject refs — errors now fail immediately instead of waiting 15s
  • Fix memory leak: timeout in Promise.race is now cleared in finally
  • Note: also switch Cloudflare widget from Invisible → Managed mode in dashboard

Type of Change

  • Bug fix

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link

vercel bot commented Mar 25, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Mar 25, 2026 3:29am

Request Review

@cursor
Copy link

cursor bot commented Mar 25, 2026

PR Summary

Medium Risk
Touches authentication flows by removing captcha enforcement on /sign-in/email and changing signup captcha token acquisition; mistakes could impact sign-in availability or bot protection.

Overview
Removes Cloudflare Turnstile captcha from the login UI and no longer sends the x-captcha-response header on email sign-in.

Reworks signup captcha handling to use Turnstile onSuccess/onError/onExpire callbacks with an explicit timeout (cleared in finally) so failures surface immediately instead of silently hanging.

Updates server-side captcha configuration to only protect /sign-up/email (drops /sign-in/email from captcha-enforced endpoints).

Written by Cursor Bugbot for commit ec8e276. Configure here.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 25, 2026

Greptile Summary

This PR fixes two related captcha issues in the auth flows: it completely removes Turnstile from the login page (where it was silently timing out and blocking legitimate users), and replaces the broken getResponsePromise-based approach on signup with the canonical onSuccess/onError/onExpire callback pattern wired to resolve/reject refs. The server-side captcha endpoint list is updated to match, keeping the bot-protection gate only on registration.

  • Login captcha removed: Turnstile widget, turnstileRef, turnstileSiteKey, token execution logic, and the x-captcha-response request header are all stripped from login-form.tsx. The login route is also removed from the server-side endpoints array in auth.ts, so the backend no longer rejects sign-in requests that lack a captcha token.
  • Signup captcha flow fixed: Promise.race replaces the getResponsePromise(15_000) call. A captchaResolveRef / captchaRejectRef pair is stored on the component and wired to the Turnstile onSuccess, onError, and onExpire callbacks so errors propagate immediately rather than silently waiting 15 seconds.
  • Memory leak fixed: clearTimeout(timeoutId) is called in the finally block, ensuring the 15-second timer is always cancelled once the race settles — regardless of which branch wins.
  • Widget mode updated: The size: 'invisible' Turnstile option is removed from the signup form (consistent with the planned Cloudflare dashboard switch to Managed mode), so the widget renders visibly inline in the form when executing.

Confidence Score: 5/5

  • Safe to merge — the changes are well-scoped bug fixes with no regressions; optional chaining correctly guards all out-of-band callback invocations.
  • All three files are narrow, targeted changes. The captcha removal from login is cleanly executed with no dangling references. The signup rewrite uses a correct and idiomatic Promise pattern; the finally block properly nulls refs and clears the timeout so there are no leaks or double-settle risks. The optional chaining on captchaResolveRef.current?.(token) / captchaRejectRef.current?.() handles out-of-band Turnstile events (e.g. a token expiring between attempts) safely as no-ops. Server-side endpoint list is consistent with the client change.
  • No files require special attention.

Important Files Changed

Filename Overview
apps/sim/app/(auth)/login/login-form.tsx Cleanly removes all Turnstile captcha code from login — widget, refs, token logic, and request header — leaving a simpler sign-in flow with no functional regressions.
apps/sim/app/(auth)/signup/signup-form.tsx Replaces the broken getResponsePromise approach with a Promise.race + onSuccess/onError/onExpire callback pattern; fixes the 15 s silent timeout and clears the timeout ID in finally to prevent the memory leak. One edge case worth understanding: onExpire can also fire outside an active attempt (token ageing), but the optional chaining on captchaRejectRef.current?.() makes it a safe no-op in that scenario.
apps/sim/lib/auth/auth.ts Removes /sign-in/email from the server-side captcha endpoint list, correctly keeping the constraint only on /sign-up/email to match the new UI behaviour.

Sequence Diagram

sequenceDiagram
    participant U as User
    participant F as SignupForm
    participant TW as Turnstile Widget
    participant CF as Cloudflare
    participant API as /sign-up/email

    U->>F: Submit form
    F->>TW: widget.reset()
    F->>F: Start Promise.race (15s timeout)
    F->>TW: widget.execute()
    TW->>CF: Challenge request
    CF-->>TW: Challenge response
    alt Success
        TW->>F: onSuccess(token)
        F->>F: captchaResolveRef.current(token)
        F->>API: POST with x-captcha-response header
        API-->>F: 200 OK
        F->>U: Redirect to /verify
    else Error
        TW->>F: onError()
        F->>F: captchaRejectRef.current(Error)
        F->>U: Show "Captcha verification failed"
    else Expire
        TW->>F: onExpire()
        F->>F: captchaRejectRef.current(Error)
        F->>U: Show "Captcha verification failed"
    else Timeout (15s)
        F->>F: setTimeout fires, reject
        F->>U: Show "Captcha verification failed"
    end
    Note over F: finally: clearTimeout, null out refs

    Note over F,API: Login: no captcha at all
    U->>F: Submit login form
    F->>API: POST /sign-in/email (no captcha header)
    API-->>F: Response
Loading

Reviews (2): Last reviewed commit: "fix(auth): show Turnstile widget at norm..." | Re-trigger Greptile

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

@waleedlatif1 waleedlatif1 merged commit 228578e into staging Mar 25, 2026
12 checks passed
@waleedlatif1 waleedlatif1 deleted the fix/hcap branch March 25, 2026 03:36
Sg312 pushed a commit that referenced this pull request Mar 25, 2026
* fix(auth): remove captcha from login, fix signup captcha flow

* fix(auth): show Turnstile widget at normal size for Managed mode challenges
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant