hCaptcha

Gem Version

Credits

Overview

License: MIT
Bugs: https://github.com/firstmoversadvantage/hcaptcha/issues

This gem provides helper methods for the hCaptcha API. In your views you can use the hcaptcha_tags method to embed the needed javascript, and you can validate in your controllers with verify_hcaptcha or verify_hcaptcha!.

Obtaining a key and setup

Go to the hCaptcha signup page to obtain API keys. You'll also need to set a hostname that your application will run from, even for local development. hCaptcha will not work if your application is being served from localhost or 127.0.0.1. You will need to add a hosts entry for local development. See the hCaptcha docs for how to do this.

The hostname you set it to must be a real hostname, since hCaptcha validates it when you create it in the portal. For example, example.fmadata.com does not have a DNS record, but mydomain.com does. The DNS record doesn't need to point to your application though, it just has to exist - that's why we added the record into the local hosts file.

Installation

FIrst, add the gem to your bundle:

bundle add hcaptcha

Then, set the following environment variables:

  • HCAPTCHA_SECRET_KEY
  • HCAPTCHA_SITE_KEY

💡 You should keep keys out of your codebase with external environment variables (using your shell's export command), Rails (< 5.2) secrets, Rails (5.2+) credentials, the dotenv or figaro gems, …

Usage

First, add hcaptcha_tags to the forms you want to protect:

<%= form_for @foo do |f| %>
  # …
  <%= hcaptcha_tags %>
  # …
<% end %>

Then, add verify_hcaptcha logic to each form action that you've protected:

# app/controllers/users_controller.rb
@user = User.new(params[:user].permit(:name))
if verify_hcaptcha(model: @user) && @user.save
  redirect_to @user
else
  render 'new'
end

If you are not using Rails, you should:

  • include Hcaptcha::Adapters::ViewMethods where you need recaptcha_tags
  • include Hcaptcha::Adapters::ControllerMethods where you need verify_hcaptcha

API details

hcaptcha_tags(options = {})

Use in your views to render the JavaScript widget.

Available options:

Option Description
:badge legacy, ignored
:callback see official documentation
:chalexpired_callback see official documentation
:class Additional CSS classes added to h-captcha on the placeholder
:close_callback see official documentation
:error_callback see official documentation
:expired_callback see official documentation
:external_script alias for :script option
:hl see official documentation and available language codes
:open_callback see official documentation
:nonce Add a nonce="…" attribute to the <script> tag
:onload see official documentation
:recaptchacompat see official documentation
:render see official documentation
:script_async Add async attribute to the <script> tag (default: true)
:script_defer Add defer attribute to the <script> tag (default: true)
:script Generate the <script> tag (default: true)
:site_key Set hCaptcha Site Key (overrides HCAPTCHA_SITE_KEY environment variable)
:size see official documentation
:stoken legacy, raises an exception
:ssl legacy, raises an exception
:theme see official documentation (default: :dark)
:type legacy, ignored
:ui legacy, ignored

ℹ️ Unkown options will be passed directly as attributes to the placeholder element.

For example, hcaptcha_tags(foo: "bar") will generate the default script tag and the following placeholder tag:

<div class="h-captcha" data-sitekey="…" foo="bar"></div>

verify_recaptcha

This method returns true or false after processing the response token from the hCaptcha widget. This is usually called from your controller.

Passing in the ActiveRecord object via model: object is optional. If you pass a model—and the captcha fails to verify—an error will be added to the object for you to use (available as object.errors).

Why isn't this a model validation? Because that violates MVC. You can use it like this, or how ever you like.

Some of the options available:

Option Description
:model Model to set errors.
:attribute Model attribute to receive errors. (default: :base)
:message Custom error message.
:secret_key Override the secret API key from the configuration.
:timeout The number of seconds to wait for hCaptcha servers before give up. (default: 3)
:response Custom response parameter. (default: params['g-recaptcha-response'])
:hostname Expected hostname or a callable that validates the hostname, see domain validation and hostname docs. (default: nil, but can be changed by setting config.hostname)
:env Current environment. The request to verify will be skipped if the environment is specified in configuration under skip_verify_env

I18n support

hCaptcha supports the I18n gem (it comes with English translations) To override or add new languages, add to config/locales/*.yml

# config/locales/en.yml
en:
  recaptcha:
    errors:
      verification_failed: 'hCaptcha was incorrect, please try again.'
      recaptcha_unreachable: 'hCaptcha verification server error, please try again.'

Testing

By default, hCaptcha is skipped in "test" and "cucumber" env. To enable it during test:

Hcaptcha.configuration.skip_verify_env.delete("test")