-
Notifications
You must be signed in to change notification settings - Fork 444
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 have 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:
Assuming PR#431 has not been merged:
- 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-turnstile
classname 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_reply
method in the controller, as if this were a v3 call. The response body does not contain ascore
param 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-cdata
in 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