Created
August 1, 2023 20:11
-
-
Save lenilsonjr/0d51a12c8e5fe90abde64385eeaf943e to your computer and use it in GitHub Desktop.
Cloudflare Turnstile on Rails
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ApplicationController < ActionController::Base | |
# ... | |
def protect_with_cf_turnstile! | |
token = params['cf-turnstile-response'] | |
ip = request.remote_ip | |
secret = Rails.application.credentials.dig(:cloudfare, :turnstile, :secret_key) #Ur site secret | |
# Prepare the form data | |
body = { :secret => secret, :response => token, :remoteip => ip } | |
# Validate the token by calling the "/siteverify" API endpoint. | |
url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify' | |
conn = Faraday.new | |
response = conn.post do |req| | |
req.url url | |
req.body = body | |
end | |
outcome = JSON.parse(response.body) | |
unless outcome['success'] | |
Rails.logger.info "CF Turnstile failed for #{ip}" | |
redirect_to "/403" and return | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%= simple_form_for( | |
User.new, | |
url: registration_path(:user), | |
data: { | |
controller: "turnstile", | |
turbo_frame: "_top" | |
}, html: { class: "" } | |
) do |f| %> | |
<div> | |
<input name="cf-turnstile-response" value="" data-turnstile-target="input" type="hidden" /> | |
<label for="email" class="sr-only">Ur email</label> | |
<%= f.input_field :email, placeholder: "Seu e-mail de trabalho", class: "", required: true, autofocus: false, autocomplete: "email" %> | |
<button | |
type="submit" | |
data-turnstile-target="button" | |
> | |
Submit | |
</button> | |
</div> | |
<div data-turnstile-target="container"></div> | |
<% end %> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Thanks @marckohlbrugge!!! | |
import { Controller } from "@hotwired/stimulus" | |
// Connects to data-controller="turnstile" | |
export default class extends Controller { | |
static values = { siteKey: String } | |
static targets = [ "button", "container", "input" ] | |
connect() { | |
// https://developers.cloudflare.com/turnstile/reference/testing/ | |
this.siteKeyValue = "" // ur site public key or test key | |
if (!window.turnstile) { | |
this.loadTurnstileScript() | |
} | |
this.element.addEventListener("submit", (event) => { | |
if (this.inputTarget.value === "") { | |
event.preventDefault() | |
this.initTurnstile() | |
} | |
}) | |
} | |
loadTurnstileScript() { | |
const script = document.createElement("script") | |
script.src = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit&onload=onTurnstileLoad" | |
script.defer = "defer" | |
script.async = true | |
window.onTurnstileLoad = () => {} | |
document.body.appendChild(script) | |
} | |
disconnect() { | |
if (this.widgetId) { | |
turnstile.remove(this.widgetId) | |
} | |
} | |
disableButton() { | |
this.buttonTarget.disabled = true | |
this.buttonTarget.classList.add("cursor-not-allowed.opacity-50") | |
} | |
enableButton() { | |
this.buttonTarget.disabled = false | |
this.buttonTarget.classList.remove("cursor-not-allowed.opacity-50") | |
} | |
initTurnstile() { | |
this.disableButton() | |
this.widgetId = turnstile.render(this.containerTarget, { | |
sitekey: this.siteKeyValue, | |
theme: "light", | |
"before-interactive-callback": () => { | |
this.disableButton() | |
this.containerTarget.classList.remove("hidden") | |
}, | |
"after-interactive-callback": () => { | |
this.containerTarget.classList.add("hidden") | |
this.enableButton() | |
}, | |
callback: (token) => { | |
// Success! | |
this.inputTarget.value = token | |
this.inputTarget.form.submit() | |
}, | |
}) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class RegistrationsController < Devise::RegistrationsController | |
before_action :protect_with_cf_turnstile!, only: [:create] | |
# ... | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment