Skip to content

v1.22.0

Choose a tag to compare

@cport1 cport1 released this 19 Aug 17:54
· 21 commits to main since this release

Serves the Turnstile / reCAPTCHA / hCaptcha siteverify contract, so an existing backend integration works against FCaptcha by changing the base URL.

Added

  • POST /turnstile/v0/siteverify, /recaptcha/api/siteverify and /siteverify on all three servers. Form-encoded and JSON bodies; secret, response, remoteip, idempotency_key; the upstream response shape and error-code vocabulary, plus score.
  • Tokens carry a signed hostname, action and cdata. The hostname is derived server-side from Origin (then Referer), so a backend can reject a token minted on another site or for a different action.
  • FCAPTCHA_VERIFY_SECRET — the credential a backend presents when verifying, separable from the signing key.
  • FCAPTCHA_ALLOWED_HOSTNAMES — optional allowlist of origins permitted to mint tokens.
  • cdata on the client: FCaptcha.execute(siteKey, { action, cdata }).

Breaking

POST /api/token/verify now requires secret. It was previously accepted and ignored, so any caller who could reach the endpoint could spend a token. Set FCAPTCHA_LEGACY_UNAUTH_VERIFY=true to restore the old behaviour for one release.

Fixed

The three servers emitted mutually unverifiable tokens: Go used padded base64url, Node unpadded, and Python signed a payload with different JSON separators. This only surfaced in a mixed fleet, where the instance validating a token is not the one that minted it. All three now emit unpadded base64url over compact sorted-key JSON and accept the old encodings, so rolling deploys and in-flight tokens are unaffected.

See Upgrading to 1.22.0.