Ruby¶
The eu_captcha gem verifies the token on the server. It has no other dependencies and uses net/http from the standard library of Ruby.
Requirements¶
The following requirements must be met:
| Requirement | Value |
|---|---|
| Ruby | From version 2.7 |
| Credentials | Public sitekey and secret from the Details view |
Install the gem¶
Install the gem:
As an alternative, add this line to the Gemfile file:
Embed the widget¶
Add the script link to each page that has a form to protect:
Add the widget to the form:
Note
In a single-page application with React, Vue, or Angular, embed the widget with the applicable npm package. Then the gem does only the verification on the server.
Verify the token¶
Verify the transmitted token on the server:
require 'eu_captcha'
captcha = EuCaptcha::Client.new(
sitekey: ENV['EUCAPTCHA_SITE_KEY'],
secret: ENV['EUCAPTCHA_SECRET_KEY']
)
result = captcha.validate(
token: params['eu-captcha-response'],
remote_addr: request.ip
)
render_error unless result.success?
Options¶
You give these options to the constructor as keyword arguments:
| Option | Type | Default | Effect |
|---|---|---|---|
sitekey |
String | — | Public sitekey. The value is necessary. |
secret |
String | — | Secret key. The value is necessary and must not occur in the browser. |
fail_default |
Boolean | true |
Return value for the network condition and the token condition when the API is not available. true permits the transmission, false rejects it. |
check_cdn_headers |
Boolean | true |
Gets the IP address of the visitor from the HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR, and HTTP_X_REAL_IP headers of the Rack environment before REMOTE_ADDR is used. |
verify_url |
String | Address of the production environment | Overwrites the address of the /verify endpoint. Use the option for tests. |
credentials_url |
String | Address of the production environment | Overwrites the address of the /verify-credentials endpoint. |
The result object¶
validate gives an EuCaptcha::Result object with these methods:
| Method | Return value |
|---|---|
success? |
true when the API was available and the token is valid. |
success_network? |
true when the call of the API completed without a network error or a transmission error. |
success_token? |
true when the API reported the transmitted token as valid. |
train |
true, false, or nil. |
The separate query tells a failed challenge from a malfunction of the API:
result = captcha.validate(token: params['eu-captcha-response'], remote_addr: request.ip)
unless result.success_network?
# Could not reach the API — consider logging or alerting
end
unless result.success_token?
# Token was rejected — the submission is likely automated
end
Warning
train gives true when the API did not do the applicable verification and forced a positive result. This occurs when the sitekey does not exist, when the secret does not agree with it, or when the protection of the sitekey is off. success? already reads this flag and gives false in this condition. For a network error, train gives the nil value.
Verify the credentials¶
With verify_credentials, you verify the sitekey and the secret without a token from the browser, for example at the start of the application:
captcha = EuCaptcha::Client.new(
sitekey: ENV['EUCAPTCHA_SITE_KEY'],
secret: ENV['EUCAPTCHA_SECRET_KEY']
)
unless captcha.verify_credentials
# Credentials are invalid or the API is unreachable — log and alert
end
For a network error or an API error, the method gives false and causes no exception.
See Verify the sitekey and the secret.
Ruby on Rails¶
Put the credentials in config/credentials.yml.enc and make the client in an initializer file.
The config/initializers/eu_captcha.rb file:
EU_CAPTCHA = EuCaptcha::Client.new(
sitekey: Rails.application.credentials.dig(:eucaptcha, :sitekey),
secret: Rails.application.credentials.dig(:eucaptcha, :secret)
)
Verify the token in the controller:
class ContactController < ApplicationController
def create
result = EU_CAPTCHA.validate(
token: params['eu-captcha-response'],
remote_addr: request.ip,
user_agent: request.user_agent
)
unless result.success?
render json: { error: 'CAPTCHA verification failed' }, status: :unprocessable_entity
return
end
# process the form...
end
end
request.ip obeys the setting of the trusted upstream systems of Rails.
Sinatra and Rack¶
Give the Rack environment to the gem, so that the gem gets the IP address and the identifier of the browser itself:
require 'sinatra'
require 'eu_captcha'
CAPTCHA = EuCaptcha::Client.new(
sitekey: ENV['EUCAPTCHA_SITE_KEY'],
secret: ENV['EUCAPTCHA_SECRET_KEY']
)
post '/contact' do
result = CAPTCHA.validate(
token: params['eu-captcha-response'],
rack_env: env
)
halt 422, 'CAPTCHA verification failed' unless result.success?
# process the form...
end
When a Rack environment is given, validate obeys the check_cdn_headers setting.
Full example¶
See Svelte and Ruby.