Skip to content

Friendly captcha - #6546

Open
ukutaht wants to merge 12 commits into
masterfrom
friendly-captcha
Open

Friendly captcha#6546
ukutaht wants to merge 12 commits into
masterfrom
friendly-captcha

Conversation

@ukutaht

@ukutaht ukutaht commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Changes

Replaces hCaptcha with invisible Friendly Captcha. Due to the 'invisible' part, some frontend complexity is necessarily added.

NB ⚠️ Do not merge. Requires Friendly Captcha credentials to be set up on prod before deploying.

Tests

This part is manually tested.

Changelog

  • Entry has been added to changelog

Documentation

  • This change does not need a documentation update

Dark mode

  • The UI has been tested both in dark and light mode

ukutaht and others added 8 commits July 22, 2026 17:51
Switch the registration and password-reset bot protection from hCaptcha
to Friendly Captcha v2 for its privacy-first, adaptive (Smart mode)
challenge model that lets legitimate users pass without interaction.

- Verify solutions server-side against the global siteverify endpoint
  using X-API-Key header auth and a JSON body.
- Configure via FRIENDLY_CAPTCHA_SITEKEY and FRIENDLY_CAPTCHA_API_KEY.
- Gate the form submit button until the widget completes (re-disabling
  on error/expire), as recommended by Friendly Captcha.
Drop the per-form attribution slot and render a single shared attribution inside the widget component, simplifying both call sites.
@github-actions

Copy link
Copy Markdown
Preview environment👷🏼‍♀️🏗️
PR-6546

@ukutaht
ukutaht requested a review from a team July 28, 2026 09:35
@ukutaht
ukutaht marked this pull request as ready for review July 28, 2026 09:36
Comment thread lib/plausible_web/components/captcha.ex Outdated
Comment thread lib/plausible_web/components/captcha.ex

@aerosol aerosol left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@apata
apata force-pushed the friendly-captcha branch from df55330 to dee11b6 Compare August 4, 2026 14:20
Comment on lines 246 to +247
if not PlausibleWeb.Captcha.enabled?() or
PlausibleWeb.Captcha.verify(params["h-captcha-response"]) do
PlausibleWeb.Captcha.verify(params["frc-captcha-response"]) do

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nitpick: We could omit the not PlausibleWeb.Captcha.enabled?() check here (as password reset does). verify returns true if not enabled anyway.

Same goes for line 262 in this file (non-invitation register event handler).

Comment on lines +144 to +153
<.button
id="register"
type="submit"
class="w-full"
mt?={false}
x-data={"{ captchaReady: #{not PlausibleWeb.Captcha.enabled?()} }"}
x-on:frc-captcha-ready.window="captchaReady = true"
x-on:frc-captcha-reset.window="captchaReady = false"
x-bind:disabled={"!captchaReady || #{@disable_submit}"}
>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Currently, a failed submit (for whatever reason, e.g. email already exists) will use up the one-time token and the next submit is guaranteed to fail with a "Please complete the captcha" error. Only a page refresh will fix that, meaning that the user needs to fill out all the fields again.

In LiveViews, when a form submit failure comes back from the server, we should make sure to reset the captcha automatically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants