-
Notifications
You must be signed in to change notification settings - Fork 443
Cloudflare Turnstile
Turnstile is Cloudflare’s smart CAPTCHA alternative. It can be embedded into any website without sending traffic through Cloudflare and works without showing visitors a CAPTCHA.
In order to have reCAPTCHA gem use Turnstile, you will need to use v. >= 5.15.0 of this gem (with PR#431 merged), or simply monkey-patch the verification to use POST. Reason being that the server-side verification call must be done via HTTP POST instead of GET: https://developers.cloudflare.com/turnstile/migration/migrating-from-recaptcha/
- Ensuring recaptcha gem sends server-side verification via POST (Only needed for v. < 5.15.0 of this gem)
- Create lib/recaptcha.rb:
# Monkey-patching to enable verifications to be sent via POST
module Recaptcha
def self.api_verification_free(verify_hash, timeout: nil)
uri = URI.parse(configuration.verify_url)
http_instance = http_client_for(uri: uri, timeout: timeout)
request = Net::HTTP::Post.new(uri.request_uri)
request['Content-Type'] = 'application/json; charset=utf-8'
request.body = JSON.generate(verify_hash)
JSON.parse(http_instance.request(request).body)
end
end- Load it in your initializers, e.g. config/initializers/monkey_patches.rb:
require Rails.root.join('lib/recaptcha.rb')- Update your config to use the API Servers
# config/initializers/recaptcha.rb
Recaptcha.configure do |config|
# Cloudflare Turnstile
config.verify_url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify'
config.api_server_url = 'https://challenges.cloudflare.com/turnstile/v0/api.js'
end(Note that we do not include the compatibility layer in the verify_url - i.e. no ?compat=recaptcha as we will be directly using the new params)
- Turnstile only supports v2-style tags. Remove any v3-style tags and rely purely on the v2 tags
- Force the addition of the
cf-turnstileclassname on the recaptcha tag:
recaptcha_tags class: 'cf-turnstile'- If PR#461 has been merged, you need to add the json: true option to ensure that we send the data via JSON and POST:
recaptcha_tags class: 'cf-turnstile', json: true- In addition, although "actions" verification is only available in reCAPTCHA v3 service, Turnstile actually supports it with v2. However, you must supply them as data-attributes on the recaptcha tag as
data-action:
recaptcha_tags class: 'cf-turnstile', json: true, 'data-action': 'contact_us'- On the backend, you need to validate with the server verification, but you will need to specify where the params are from (
cf-turnstile-response)
- Add response param:
verify_recaptcha response: params['cf-turnstile-response']- Add request data (IP and Hostname):
verify_recaptcha response: params['cf-turnstile-response'], remoteip: request.ip, hostname: request.hostname- Add action verification:
verify_recaptcha response: params['cf-turnstile-response'], remoteip: request.ip, hostname: request.hostname, action: 'contact_us'- Voila! After calling
verify_recaptcha, the server's response will be available inrecaptcha_replymethod in the controller, as if this were a v3 call. The response body does not contain ascoreparam like in v3 however, but instead has all the information you need in terms of timestamp, hostname, action, and cdata.
Example recaptcha_reply:
{
action: "messages",
cdata: "",
challenge_ts: "2023-08-19T03:38:03.777Z",
error-codes: [],
hostname: "127.0.0.1",
metadata: {
interactive: false
},
success: true
}- If you provided
data-cdatain therecaptcha_tags, it will be returned inrecaptcha_reply[:cdata]
Need to customise your widget to stop respecting dark mode? Want to shrink that checkbox? See the recaptcha_tag configuration options (via data-attributes) available at https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/#configurations