Skip to content

Fix: restore Cloudflare Turnstile client wiring for Google signup gate - #217

Merged
ayoub3bidi merged 2 commits into
developfrom
fix/turnstile-signup-gate
Aug 4, 2026
Merged

Fix: restore Cloudflare Turnstile client wiring for Google signup gate#217
ayoub3bidi merged 2 commits into
developfrom
fix/turnstile-signup-gate

Conversation

@ayoub3bidi

@ayoub3bidi ayoub3bidi commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Contribution workflow

  • Base branch is develop: This PR targets develop, not main. (If the base is wrong, edit the PR on GitHub and change the base branch.)
  • Guidelines and docs: I have read CONTRIBUTING.md and the docs relevant to my change (DEVELOPMENT.md, ARCHITECTURE.md as needed).
  • This template: I kept the PR template structure and filled in the sections below that apply to this change.

Description

New Google signups were rejected by the before-signup hook with turnstile_failed because the Turnstile server secret was enforced while the client never sent a token in production.

Root causes: VITE_TURNSTILE_SITE_KEY was missing from Cloudflare deploy/preview CI (Vite stubbed getTurnstileToken() to always null), the Turnstile script tag had been removed from index.html, and CSP did not allow challenges.cloudflare.com. Existing accounts still signed in normally (Before User Created does not run for returning users).

This PR restores the client path end-to-end, hardens failure UX when the site key is configured, quiets Telegram noise from GET probes on before-signup, and documents/wires the public site key for CI.

Ops required after merge (not in this PR):

  1. Add GitHub Actions secret VITE_TURNSTILE_SITE_KEY (Cloudflare Turnstile site key).
  2. Confirm Supabase Edge Function secret TURNSTILE_SECRET_KEY is set.
  3. Allow hostnames on the Turnstile widget: bayanflow.com, dev.bayanflow.com, localhost (and preview hosts if testing auth on Workers previews).
  4. Redeploy before-signup so alert/405 changes go live.
  5. Keep Cloudflare Bot Fight Mode off (separate from Turnstile; needed for future Lemon Squeezy webhooks).

Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📚 Documentation update
  • 🎨 Style/UI improvement
  • ⚡ Performance improvement
  • 🧪 Test addition or improvement
  • 🔧 Chore (maintenance, dependencies, etc.)

Related Issues

Fixes #

Changes Made

  • Restored the Cloudflare Turnstile script in index.html (api.js?render=explicit).
  • Allowed https://challenges.cloudflare.com in CSP (script-src, connect-src, frame-src) and asserted it in scripts/cspHeaders.js + tests.
  • Hardened getTurnstileToken() / signInWithGoogle(): when the site key is set, missing script or challenge failure throws before calling Auth; when unset, omit metadata (local/CI fail-open).
  • Wired VITE_TURNSTILE_SITE_KEY into deploy-cloudflare.yml and preview-cloudflare.yml.
  • Documented Turnstile site key vs Supabase TURNSTILE_SECRET_KEY in .env.example.
  • before-signup: non-POST returns HTTP 405 without Telegram; turnstile_failed alerts include email and ip.
  • Expanded authService and CSP unit tests for Turnstile paths.

Algorithm Details (if applicable)

N/A

Testing

  • All existing tests pass (pnpm test:run)
  • New tests added for new functionality
  • Manual testing completed
  • Cross-browser testing (if UI changes)

Test Results

pnpm vitest run src/services/authService.test.js src/security/cspHeaders.test.js

 Test Files  2 passed (2)
      Tests  19 passed (19)

Manual verification (post-deploy)

  • Production HTML includes the Turnstile script tag.
  • Built JS is not a null-stub for Turnstile (site key inlined via CI secret).
  • New Google account signup succeeds; no turnstile_failed Telegram alert.
  • Existing account (e.g. returning Free user) still signs in.
  • GET to before-signup URL does not send a Telegram alert.

Screenshots/GIFs

N/A — auth/security wiring, no UI layout change.

Code Quality

  • Code follows the project's coding standards
  • ESLint passes (pnpm lint)
  • Prettier formatting applied (pnpm format)
  • No console errors or warnings
  • Code is properly documented with JSDoc (if applicable)

Performance Impact

  • No performance impact
  • Performance improved
  • Performance impact assessed and acceptable
  • Performance benchmarks included

Accessibility

  • Keyboard navigation works correctly
  • Screen reader compatibility maintained
  • Color contrast meets WCAG guidelines
  • Focus indicators are visible

N/A — invisible Turnstile widget; no interactive UI surface changes.

Breaking Changes

  • None

Checklist

  • I have completed the Contribution workflow checklist at the top of this template
  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published

Additional Notes

  • Without the GitHub secret VITE_TURNSTILE_SITE_KEY, production builds will again omit the token and new signups will fail while TURNSTILE_SECRET_KEY remains set on Supabase.
  • Bot Fight Mode is intentionally left off; Turnstile only gates signup via the Before User Created hook and does not replace or conflict with webhook delivery for future Lemon Squeezy work.

Reviewer Guidelines:

  • Check that all tests pass
  • Verify code follows project standards
  • Test the changes locally
  • Review for security implications
  • Ensure documentation is updated
  • Confirm VITE_TURNSTILE_SITE_KEY is present in repo secrets before relying on production signup

Summary by CodeRabbit

  • New Features

    • Added invisible Cloudflare Turnstile protection to signup and Google sign-in flows.
    • Added configuration support for enabling Turnstile across production and preview builds.
  • Bug Fixes

    • Authentication now blocks requests when Turnstile verification fails, times out, or is unavailable.
    • Improved rejection alerts with the associated email address.
    • Non-POST signup requests now return a clear method-not-allowed response.
  • Security

    • Updated security policies to support Cloudflare challenge resources.

@ayoub3bidi ayoub3bidi self-assigned this Aug 4, 2026
@github-actions github-actions Bot added ci Workflows tests labels Aug 4, 2026
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ayoub3bidi, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 27 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ef172309-3523-488c-9aab-cd2be5c88cc2

📥 Commits

Reviewing files that changed from the base of the PR and between e16943c and 672647f.

📒 Files selected for processing (2)
  • src/services/authService.test.js
  • supabase/functions/before-signup/index.ts
📝 Walkthrough

Walkthrough

The PR configures Cloudflare Turnstile for builds and browser loading, updates CSP validation, enforces verification failures in authentication, forwards successful tokens, and refines Supabase signup responses and alerts.

Changes

Turnstile integration

Layer / File(s) Summary
Turnstile configuration and runtime access
.env.example, .github/workflows/*, index.html, public/_headers, scripts/cspHeaders.js, src/security/cspHeaders.test.js
Adds the Turnstile site-key configuration, loads the client script, permits Cloudflare challenge resources, and validates the required CSP directives.
Authentication verification and tests
src/services/authService.js, src/services/authService.test.js
Rejects missing, timed-out, or failed Turnstile verification when configured. Successful tokens are forwarded as cf_turnstile_response metadata.
Signup request and rejection handling
supabase/functions/before-signup/index.ts
Returns HTTP 405 JSON for non-POST requests and includes the signup email in Turnstile rejection alerts.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested labels: config

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: restoring Cloudflare Turnstile client wiring for the Google signup gate.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/turnstile-signup-gate

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

Preview for Bayan Flow Staging ready!

Name Link
🔨 Latest commit 672647f
🔍 Latest deploy log https://github.com/ayoub3bidi/bayan-flow/actions/runs/30896130723
😎 Deploy Preview https://pr-217-bayan-flow-staging.ayoub3bidi.workers.dev
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

Preview alias pr-217 on the staging worker. Updates automatically with new commits.

@codecov

codecov Bot commented Aug 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/services/authService.test.js`:
- Around line 153-175: Add a fake-timer test alongside the existing Turnstile
failure tests in the authService test suite, configuring VITE_TURNSTILE_SITE_KEY
and a turnstile.render mock that invokes no callback; advance the clock by 10
seconds, assert signInWithGoogle rejects, and verify
supabaseAuthMock.signInWithIdToken was not called. Restore timers after the
test.

In `@supabase/functions/before-signup/index.ts`:
- Around line 95-97: Update the 405 response returned by the before-signup
handler to include an Allow header set to POST alongside the existing
Content-Type header, while preserving the current error body and status.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4ffffaf6-b175-4446-a664-dcd27a4aa5f9

📥 Commits

Reviewing files that changed from the base of the PR and between 2055487 and e16943c.

📒 Files selected for processing (10)
  • .env.example
  • .github/workflows/deploy-cloudflare.yml
  • .github/workflows/preview-cloudflare.yml
  • index.html
  • public/_headers
  • scripts/cspHeaders.js
  • src/security/cspHeaders.test.js
  • src/services/authService.js
  • src/services/authService.test.js
  • supabase/functions/before-signup/index.ts

Comment thread src/services/authService.test.js
Comment thread supabase/functions/before-signup/index.ts Outdated
- Add fake-timer test for Turnstile challenge timeout rejection path
- Return Allow: POST header on before-signup 405 responses
@ayoub3bidi
ayoub3bidi merged commit 0b3eaca into develop Aug 4, 2026
15 checks passed
@ayoub3bidi
ayoub3bidi deleted the fix/turnstile-signup-gate branch August 4, 2026 09:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci Workflows tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant