recaptcha 0.3.6 → 5.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +141 -0
- data/README.md +520 -0
- data/lib/recaptcha.rb +89 -15
- data/lib/recaptcha/adapters/controller_methods.rb +94 -0
- data/lib/recaptcha/adapters/view_methods.rb +26 -0
- data/lib/recaptcha/configuration.rb +34 -24
- data/lib/recaptcha/helpers.rb +322 -0
- data/lib/recaptcha/rails.rb +3 -4
- data/lib/recaptcha/railtie.rb +31 -11
- data/lib/recaptcha/version.rb +3 -1
- data/rails/locales/en.yml +5 -0
- metadata +98 -35
- data/.gitignore +0 -3
- data/CHANGELOG +0 -33
- data/Gemfile +0 -3
- data/README.rdoc +0 -146
- data/Rakefile +0 -9
- data/init.rb +0 -5
- data/lib/recaptcha/client_helper.rb +0 -69
- data/lib/recaptcha/merb.rb +0 -4
- data/lib/recaptcha/verify.rb +0 -75
- data/recaptcha.gemspec +0 -24
- data/test/recaptcha_test.rb +0 -62
- data/test/verify_recaptcha_test.rb +0 -151
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 849f0b2edee6bde557c0bdab3802dfbc7528a5e777709a110b6c4f228842c1a1
|
4
|
+
data.tar.gz: ebf65ad28a50a06363bc7544df1ef2639aefebbeace7f15cd97fd1ffc047764c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68f606e91517a8062d7afe48e43d306383f4ef4c83ac4c61179f9ea58d38628230768865604a61758bfd3d5b0d1a2197a981b764169153e36ef0bcf7bedb86d9
|
7
|
+
data.tar.gz: c87318df857db04fb2485c73ba686d82f3d18ed87cc0db8f006bbe2f456179218aeb25b1477017b80240504329cc9d02acd9b09457ae927997a5b61dd6849228
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
## Next
|
2
|
+
|
3
|
+
## 5.5.0
|
4
|
+
* add `recaptcha_reply` controller method for better debugging/inspection
|
5
|
+
|
6
|
+
## 5.4.1
|
7
|
+
* fix v2 vs 'data' postfix
|
8
|
+
|
9
|
+
## 5.4.0
|
10
|
+
* added 'data' postfix to g-recaptcha-response attribute name to avoid collisions
|
11
|
+
|
12
|
+
## 5.3.0
|
13
|
+
* turbolinks support
|
14
|
+
|
15
|
+
## 5.2.0
|
16
|
+
* remove dependency on rails methods
|
17
|
+
|
18
|
+
## 5.1.0
|
19
|
+
* Added default translations for rails/i18n
|
20
|
+
* use recaptcha.net for the script tag
|
21
|
+
|
22
|
+
## 5.0.0
|
23
|
+
* Changed host to Recaptcha.net
|
24
|
+
* Add v3 API support
|
25
|
+
* Renamed `Recaptcha::ClientHelper` to `Recaptcha::Adapters::ViewMethods`
|
26
|
+
* Renamed `Recaptcha::Verify` to `Recaptcha::Adapters::ControllerMethods`
|
27
|
+
|
28
|
+
## 4.12.0 - 2018-08-30
|
29
|
+
* add `input` option to `invisible_recaptcha_tags`'s `ui` setting
|
30
|
+
|
31
|
+
## 4.11.1 - 2018-08-08
|
32
|
+
* leave `tabindex` attribute alone for `invisible_recaptcha_tags`
|
33
|
+
|
34
|
+
## 4.11.0 - 2018-08-06
|
35
|
+
* prefer RAILS_ENV over RACK_ENV #286
|
36
|
+
|
37
|
+
## 4.0.0 - 2016-11-14
|
38
|
+
* public_key -> site_key and private_key -> secret_key
|
39
|
+
|
40
|
+
## 3.4.0 - 2016-11-01
|
41
|
+
* Update fallback html
|
42
|
+
|
43
|
+
## 3.2.0 - 2016-06-13
|
44
|
+
* remove SKIP_VERIFY_ENV constant, use `skip_verify_env` instance variable instead
|
45
|
+
|
46
|
+
## 3.1.0 - 2016-06-10
|
47
|
+
* better error messages
|
48
|
+
* frozen constants
|
49
|
+
|
50
|
+
## 3.0.0 - 2016-05-27
|
51
|
+
* remove all non-ssl options
|
52
|
+
|
53
|
+
## 2.3.0 - 2016-05-25
|
54
|
+
* enable ssl verification by default ... disable via `disable_ssl_verification = true`
|
55
|
+
|
56
|
+
## 2.2.0 - 2016-05-23
|
57
|
+
* Add global hostname validator config
|
58
|
+
* Clean up after with_configuration exception
|
59
|
+
|
60
|
+
## 2.1.0 - 2016-05-19
|
61
|
+
* do not query google if repactcha was not submitted
|
62
|
+
|
63
|
+
## 2.0.0 - 2016-05-17
|
64
|
+
* remove stoken support, must use custom domain verification or domain whitelist
|
65
|
+
|
66
|
+
## 1.3.0 - 2016-04-07
|
67
|
+
* do not set model error and flash
|
68
|
+
|
69
|
+
## 1.2.0 - 2016-04-01
|
70
|
+
* custom domain validation
|
71
|
+
|
72
|
+
## 1.1.0 - 2016-01-27
|
73
|
+
* support RACK_ENV
|
74
|
+
|
75
|
+
## 1.0.2 - 2015-11-30
|
76
|
+
* nice deprecations for api_version
|
77
|
+
|
78
|
+
## 1.0.1 - 2015-11-30
|
79
|
+
* no longer defines `Rails` when `recaptcha/rails` is required
|
80
|
+
|
81
|
+
## 1.0.0 - 2015-11-30
|
82
|
+
* remove api v1 support
|
83
|
+
* remove ssl_api_server_url, nonssl_api_server_url, change api_server_url to always need ssl option
|
84
|
+
* removed activesupport dependency for .to_query
|
85
|
+
* made flash and models both have descriptive errors
|
86
|
+
|
87
|
+
## 0.6.0 - 2015-11-19
|
88
|
+
* extract token module
|
89
|
+
* need to use `gem "recaptcha", require: "recaptcha/rails"` to get rails helpers installed
|
90
|
+
|
91
|
+
## 0.5.0 - 2015-11-18
|
92
|
+
* size option
|
93
|
+
* support disabling stoken
|
94
|
+
* support Rails.env
|
95
|
+
|
96
|
+
## 0.4.0 / 2015-03-22
|
97
|
+
|
98
|
+
* Add support for ReCaptcha v2 API
|
99
|
+
* V2 API requires `g-recaptcha-response` parameters; https://github.com/ambethia/recaptcha/pull/114
|
100
|
+
|
101
|
+
## 0.3.6 / 2012-01-07
|
102
|
+
|
103
|
+
* Many documentation changes
|
104
|
+
* Fixed deprecations in dependencies
|
105
|
+
* Protocol relative JS includes
|
106
|
+
* Fixes for options hash
|
107
|
+
* Fixes for failing tests
|
108
|
+
|
109
|
+
## 0.3.5 / 2012-05-02
|
110
|
+
|
111
|
+
* I18n for error messages
|
112
|
+
* Rails: delete flash keys if unused
|
113
|
+
|
114
|
+
## 0.3.4 / 2011-12-13
|
115
|
+
|
116
|
+
* Rails 3
|
117
|
+
* Remove jeweler
|
118
|
+
|
119
|
+
## 0.2.2 / 2009-09-14
|
120
|
+
|
121
|
+
* Add a timeout to the validator
|
122
|
+
* Give the documentation some love
|
123
|
+
|
124
|
+
## 0.2.1 / 2009-09-14
|
125
|
+
|
126
|
+
* Removed Ambethia namespace, and restructured classes a bit
|
127
|
+
* Added an example rails app in the example-rails branch
|
128
|
+
|
129
|
+
## 0.2.0 / 2009-09-12
|
130
|
+
|
131
|
+
* RecaptchaOptions AJAX API Fix
|
132
|
+
* Added 'cucumber' as a test environment to skip
|
133
|
+
* Ruby 1.9 compat fixes
|
134
|
+
* Added option :message => 'Custom error message' to verify_recaptcha
|
135
|
+
* Removed dependency on ActiveRecord constant
|
136
|
+
* Add I18n
|
137
|
+
|
138
|
+
## 0.1.0 / 2008-2-8
|
139
|
+
|
140
|
+
* 1 major enhancement
|
141
|
+
* Initial Gem Release
|
data/README.md
ADDED
@@ -0,0 +1,520 @@
|
|
1
|
+
# reCAPTCHA
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/recaptcha.svg)](https://badge.fury.io/rb/recaptcha)
|
3
|
+
|
4
|
+
Author: Jason L Perry (http://ambethia.com)<br/>
|
5
|
+
Copyright: Copyright (c) 2007-2013 Jason L Perry<br/>
|
6
|
+
License: [MIT](http://creativecommons.org/licenses/MIT/)<br/>
|
7
|
+
Info: https://github.com/ambethia/recaptcha<br/>
|
8
|
+
Bugs: https://github.com/ambethia/recaptcha/issues<br/>
|
9
|
+
|
10
|
+
This gem provides helper methods for the [reCAPTCHA API](https://www.google.com/recaptcha). In your
|
11
|
+
views you can use the `recaptcha_tags` method to embed the needed javascript, and you can validate
|
12
|
+
in your controllers with `verify_recaptcha` or `verify_recaptcha!`, which raises an error on
|
13
|
+
failure.
|
14
|
+
|
15
|
+
## Obtaining a key
|
16
|
+
|
17
|
+
Go to the [reCAPTCHA admin console](https://www.google.com/recaptcha/admin) to obtain a reCAPTCHA API key.
|
18
|
+
|
19
|
+
The reCAPTCHA type(s) that you choose for your key will determine which methods to use below.
|
20
|
+
|
21
|
+
| reCAPTCHA type | Methods to use | Description |
|
22
|
+
|----------------------------------------------|----------------|-------------|
|
23
|
+
| v3 | [`recaptcha_v3`](#recaptcha_v3) | Verify requests with a [score](https://developers.google.com/recaptcha/docs/v3#score)
|
24
|
+
| v2 Checkbox<br/>("I'm not a robot" Checkbox) | [`recaptcha_tags`](#recaptcha_tags) | Validate requests with the "I'm not a robot" checkbox |
|
25
|
+
| v2 Invisible<br/>(Invisible reCAPTCHA badge) | [`invisible_recaptcha_tags`](#invisible_recaptcha_tags) | Validate requests in the background |
|
26
|
+
|
27
|
+
Note: You can _only_ use methods that match your key's type. You cannot use v2 methods with a v3
|
28
|
+
key or use `recaptcha_tags` with a v2 Invisible key, for example. Otherwise you will get an
|
29
|
+
error like "Invalid key type" or "This site key is not enabled for the invisible captcha."
|
30
|
+
|
31
|
+
Note: Enter `localhost` or `127.0.0.1` as the domain if using in development with `localhost:3000`.
|
32
|
+
|
33
|
+
## Rails Installation
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
gem "recaptcha"
|
37
|
+
```
|
38
|
+
|
39
|
+
You can keep keys out of the code base with environment variables or with Rails [secrets](https://api.rubyonrails.org/classes/Rails/Application.html#method-i-secrets).<br/>
|
40
|
+
|
41
|
+
In development, you can use the [dotenv](https://github.com/bkeepers/dotenv) gem. (Make sure to add it above `gem 'recaptcha'`.)
|
42
|
+
|
43
|
+
See [Alternative API key setup](#alternative-api-key-setup) for more ways to configure or override
|
44
|
+
keys. See also the
|
45
|
+
[Configuration](https://www.rubydoc.info/github/ambethia/recaptcha/master/Recaptcha/Configuration)
|
46
|
+
documentation.
|
47
|
+
|
48
|
+
```shell
|
49
|
+
export RECAPTCHA_SITE_KEY = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
|
50
|
+
export RECAPTCHA_SECRET_KEY = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
|
51
|
+
```
|
52
|
+
|
53
|
+
Add `recaptcha_tags` to the forms you want to protect:
|
54
|
+
|
55
|
+
```erb
|
56
|
+
<%= form_for @foo do |f| %>
|
57
|
+
# …
|
58
|
+
<%= recaptcha_tags %>
|
59
|
+
# …
|
60
|
+
<% end %>
|
61
|
+
```
|
62
|
+
|
63
|
+
Then, add `verify_recaptcha` logic to each form action that you've protected:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
# app/controllers/users_controller.rb
|
67
|
+
@user = User.new(params[:user].permit(:name))
|
68
|
+
if verify_recaptcha(model: @user) && @user.save
|
69
|
+
redirect_to @user
|
70
|
+
else
|
71
|
+
render 'new'
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
## Sinatra / Rack / Ruby installation
|
76
|
+
|
77
|
+
See [sinatra demo](/demo/sinatra) for details.
|
78
|
+
|
79
|
+
- add `gem 'recaptcha'` to `Gemfile`
|
80
|
+
- set env variables
|
81
|
+
- `include Recaptcha::Adapters::ViewMethods` where you need `recaptcha_tags`
|
82
|
+
- `include Recaptcha::Adapters::ControllerMethods` where you need `verify_recaptcha`
|
83
|
+
|
84
|
+
|
85
|
+
## reCAPTCHA v2 API and Usage
|
86
|
+
|
87
|
+
### `recaptcha_tags`
|
88
|
+
|
89
|
+
Use this when your key's reCAPTCHA type is "v2 Checkbox".
|
90
|
+
|
91
|
+
The following options are available:
|
92
|
+
|
93
|
+
| Option | Description |
|
94
|
+
|---------------------|-------------|
|
95
|
+
| `:theme` | Specify the theme to be used per the API. Available options: `dark` and `light`. (default: `light`) |
|
96
|
+
| `:ajax` | Render the dynamic AJAX captcha per the API. (default: `false`) |
|
97
|
+
| `:site_key` | Override site API key from configuration |
|
98
|
+
| `:error` | Override the error code returned from the reCAPTCHA API (default: `nil`) |
|
99
|
+
| `:size` | Specify a size (default: `nil`) |
|
100
|
+
| `:nonce` | Optional. Sets nonce attribute for script. Can be generated via `SecureRandom.base64(32)`. (default: `nil`) |
|
101
|
+
| `:id` | Specify an html id attribute (default: `nil`) |
|
102
|
+
| `:callback` | Optional. Name of success callback function, executed when the user submits a successful response |
|
103
|
+
| `:expired_callback` | Optional. Name of expiration callback function, executed when the reCAPTCHA response expires and the user needs to re-verify. |
|
104
|
+
| `:error_callback` | Optional. Name of error callback function, executed when reCAPTCHA encounters an error (e.g. network connectivity) |
|
105
|
+
| `:noscript` | Include `<noscript>` content (default: `true`)|
|
106
|
+
|
107
|
+
[JavaScript resource (api.js) parameters](https://developers.google.com/recaptcha/docs/invisible#js_param):
|
108
|
+
|
109
|
+
| Option | Description |
|
110
|
+
|---------------------|-------------|
|
111
|
+
| `:onload` | Optional. The name of your callback function to be executed once all the dependencies have loaded. (See [explicit rendering](https://developers.google.com/recaptcha/docs/display#explicit_render)) |
|
112
|
+
| `:render` | Optional. Whether to render the widget explicitly. Defaults to `onload`, which will render the widget in the first g-recaptcha tag it finds. (See [explicit rendering](https://developers.google.com/recaptcha/docs/display#explicit_render)) |
|
113
|
+
| `:hl` | Optional. Forces the widget to render in a specific language. Auto-detects the user's language if unspecified. (See [language codes](https://developers.google.com/recaptcha/docs/language)) |
|
114
|
+
| `:script` | Alias for `:external_script`. If you do not need to add a script tag by helper you can set the option to `false`. It's necessary when you add a script tag manualy (default: `true`). |
|
115
|
+
| `:external_script` | Set to `false` to avoid including a script tag for the external `api.js` resource. Useful when including multiple `recaptcha_tags` on the same page. |
|
116
|
+
| `:script_async` | Set to `false` to load the external `api.js` resource synchronously. (default: `true`) |
|
117
|
+
| `:script_defer` | Set to `true` to defer loading of external `api.js` until HTML documen has been parsed. (default: `true`) |
|
118
|
+
|
119
|
+
Any unrecognized options will be added as attributes on the generated tag.
|
120
|
+
|
121
|
+
You can also override the html attributes for the sizes of the generated `textarea` and `iframe`
|
122
|
+
elements, if CSS isn't your thing. Inspect the [source of `recaptcha_tags`](https://github.com/ambethia/recaptcha/blob/master/lib/recaptcha/helpers.rb)
|
123
|
+
to see these options.
|
124
|
+
|
125
|
+
Note that you cannot submit/verify the same response token more than once or you will get a
|
126
|
+
`timeout-or-duplicate` error code. If you need reset the captcha and generate a new response token,
|
127
|
+
then you need to call `grecaptcha.reset()`.
|
128
|
+
|
129
|
+
### `verify_recaptcha`
|
130
|
+
|
131
|
+
This method returns `true` or `false` after processing the response token from the reCAPTCHA widget.
|
132
|
+
This is usually called from your controller, as seen [above](#rails-installation).
|
133
|
+
|
134
|
+
Passing in the ActiveRecord object via `model: object` is optional. If you pass a `model`—and the
|
135
|
+
captcha fails to verify—an error will be added to the object for you to use (available as
|
136
|
+
`object.errors`).
|
137
|
+
|
138
|
+
Why isn't this a model validation? Because that violates MVC. You can use it like this, or how ever
|
139
|
+
you like.
|
140
|
+
|
141
|
+
Some of the options available:
|
142
|
+
|
143
|
+
| Option | Description |
|
144
|
+
|----------------|-------------|
|
145
|
+
| `:model` | Model to set errors.
|
146
|
+
| `:attribute` | Model attribute to receive errors. (default: `:base`)
|
147
|
+
| `:message` | Custom error message.
|
148
|
+
| `:secret_key` | Override the secret API key from the configuration.
|
149
|
+
| `:timeout` | The number of seconds to wait for reCAPTCHA servers before give up. (default: `3`)
|
150
|
+
| `:response` | Custom response parameter. (default: `params['g-recaptcha-response-data']`)
|
151
|
+
| `:hostname` | Expected hostname or a callable that validates the hostname, see [domain validation](https://developers.google.com/recaptcha/docs/domain_validation) and [hostname](https://developers.google.com/recaptcha/docs/verify#api-response) docs. (default: `nil`, but can be changed by setting `config.hostname`)
|
152
|
+
| `:env` | Current environment. The request to verify will be skipped if the environment is specified in configuration under `skip_verify_env`
|
153
|
+
|
154
|
+
|
155
|
+
### `invisible_recaptcha_tags`
|
156
|
+
|
157
|
+
Use this when your key's reCAPTCHA type is "v2 Invisible".
|
158
|
+
|
159
|
+
For more information, refer to: [Invisible reCAPTCHA](https://developers.google.com/recaptcha/docs/invisible).
|
160
|
+
|
161
|
+
This is similar to `recaptcha_tags`, with the following additional options that are only available
|
162
|
+
on `invisible_recaptcha_tags`:
|
163
|
+
|
164
|
+
| Option | Description |
|
165
|
+
|---------------------|-------------|
|
166
|
+
| `:ui` | The type of UI to render for this "invisible" widget. (default: `:button`)<br/>`:button`: Renders a `<button type="submit">` tag with `options[:text]` as the button text.<br/>`:invisible`: Renders a `<div>` tag.<br/>`:input`: Renders a `<input type="submit">` tag with `options[:text]` as the button text. |
|
167
|
+
| `:text` | The text to show for the button. (default: `"Submit"`)
|
168
|
+
| `:inline_script` | If you do not need this helper to add an inline script tag, you can set the option to `false` (default: `true`).
|
169
|
+
|
170
|
+
It also accepts most of the options that `recaptcha_tags` accepts, including the following:
|
171
|
+
|
172
|
+
| Option | Description |
|
173
|
+
|---------------------|-------------|
|
174
|
+
| `:site_key` | Override site API key from configuration |
|
175
|
+
| `:nonce` | Optional. Sets nonce attribute for script tag. Can be generated via `SecureRandom.base64(32)`. (default: `nil`) |
|
176
|
+
| `:id` | Specify an html id attribute (default: `nil`) |
|
177
|
+
| `:script` | Same as setting both `:inline_script` and `:external_script`. If you only need one or the other, use `:inline_script` and `:external_script` instead. |
|
178
|
+
| `:callback` | Optional. Name of success callback function, executed when the user submits a successful response |
|
179
|
+
| `:expired_callback` | Optional. Name of expiration callback function, executed when the reCAPTCHA response expires and the user needs to re-verify. |
|
180
|
+
| `:error_callback` | Optional. Name of error callback function, executed when reCAPTCHA encounters an error (e.g. network connectivity) |
|
181
|
+
|
182
|
+
[JavaScript resource (api.js) parameters](https://developers.google.com/recaptcha/docs/invisible#js_param):
|
183
|
+
|
184
|
+
| Option | Description |
|
185
|
+
|---------------------|-------------|
|
186
|
+
| `:onload` | Optional. The name of your callback function to be executed once all the dependencies have loaded. (See [explicit rendering](https://developers.google.com/recaptcha/docs/display#explicit_render)) |
|
187
|
+
| `:render` | Optional. Whether to render the widget explicitly. Defaults to `onload`, which will render the widget in the first g-recaptcha tag it finds. (See [explicit rendering](https://developers.google.com/recaptcha/docs/display#explicit_render)) |
|
188
|
+
| `:hl` | Optional. Forces the widget to render in a specific language. Auto-detects the user's language if unspecified. (See [language codes](https://developers.google.com/recaptcha/docs/language)) |
|
189
|
+
| `:external_script` | Set to `false` to avoid including a script tag for the external `api.js` resource. Useful when including multiple `recaptcha_tags` on the same page. |
|
190
|
+
| `:script_async` | Set to `false` to load the external `api.js` resource synchronously. (default: `true`) |
|
191
|
+
| `:script_defer` | Set to `false` to defer loading of external `api.js` until HTML documen has been parsed. (default: `true`) |
|
192
|
+
|
193
|
+
### With a single form on a page
|
194
|
+
|
195
|
+
1. The `invisible_recaptcha_tags` generates a submit button for you.
|
196
|
+
|
197
|
+
```erb
|
198
|
+
<%= form_for @foo do |f| %>
|
199
|
+
# ... other tags
|
200
|
+
<%= invisible_recaptcha_tags text: 'Submit form' %>
|
201
|
+
<% end %>
|
202
|
+
```
|
203
|
+
|
204
|
+
Then, add `verify_recaptcha` to your controller as seen [above](#rails-installation).
|
205
|
+
|
206
|
+
### With multiple forms on a page
|
207
|
+
|
208
|
+
1. You will need a custom callback function, which is called after verification with Google's reCAPTCHA service. This callback function must submit the form. Optionally, `invisible_recaptcha_tags` currently implements a JS function called `invisibleRecaptchaSubmit` that is called when no `callback` is passed. Should you wish to override `invisibleRecaptchaSubmit`, you will need to use `invisible_recaptcha_tags script: false`, see lib/recaptcha/client_helper.rb for details.
|
209
|
+
2. The `invisible_recaptcha_tags` generates a submit button for you.
|
210
|
+
|
211
|
+
```erb
|
212
|
+
<%= form_for @foo, html: {id: 'invisible-recaptcha-form'} do |f| %>
|
213
|
+
# ... other tags
|
214
|
+
<%= invisible_recaptcha_tags callback: 'submitInvisibleRecaptchaForm', text: 'Submit form' %>
|
215
|
+
<% end %>
|
216
|
+
```
|
217
|
+
|
218
|
+
```javascript
|
219
|
+
// app/assets/javascripts/application.js
|
220
|
+
var submitInvisibleRecaptchaForm = function () {
|
221
|
+
document.getElementById("invisible-recaptcha-form").submit();
|
222
|
+
};
|
223
|
+
```
|
224
|
+
|
225
|
+
Finally, add `verify_recaptcha` to your controller as seen [above](#rails-installation).
|
226
|
+
|
227
|
+
### Programmatically invoke
|
228
|
+
|
229
|
+
1. Specify `ui` option
|
230
|
+
|
231
|
+
```erb
|
232
|
+
<%= form_for @foo, html: {id: 'invisible-recaptcha-form'} do |f| %>
|
233
|
+
# ... other tags
|
234
|
+
<button type="button" id="submit-btn">
|
235
|
+
Submit
|
236
|
+
</button>
|
237
|
+
<%= invisible_recaptcha_tags ui: :invisible, callback: 'submitInvisibleRecaptchaForm' %>
|
238
|
+
<% end %>
|
239
|
+
```
|
240
|
+
|
241
|
+
```javascript
|
242
|
+
// app/assets/javascripts/application.js
|
243
|
+
document.getElementById('submit-btn').addEventListener('click', function (e) {
|
244
|
+
// do some validation
|
245
|
+
if(isValid) {
|
246
|
+
// call reCAPTCHA check
|
247
|
+
grecaptcha.execute();
|
248
|
+
}
|
249
|
+
});
|
250
|
+
|
251
|
+
var submitInvisibleRecaptchaForm = function () {
|
252
|
+
document.getElementById("invisible-recaptcha-form").submit();
|
253
|
+
};
|
254
|
+
```
|
255
|
+
|
256
|
+
|
257
|
+
## reCAPTCHA v3 API and Usage
|
258
|
+
|
259
|
+
The main differences from v2 are:
|
260
|
+
1. you must specify an [action](https://developers.google.com/recaptcha/docs/v3#actions) in both frontend and backend
|
261
|
+
1. you can choose the minimum score required for you to consider the verification a success
|
262
|
+
(consider the user a human and not a robot)
|
263
|
+
1. reCAPTCHA v3 is invisible (except for the reCAPTCHA badge) and will never interrupt your users;
|
264
|
+
you have to choose which scores are considered an acceptable risk, and choose what to do (require
|
265
|
+
two-factor authentication, show a v3 challenge, etc.) if the score falls below the threshold you
|
266
|
+
choose
|
267
|
+
|
268
|
+
For more information, refer to the [v3 documentation](https://developers.google.com/recaptcha/docs/v3).
|
269
|
+
|
270
|
+
### Examples
|
271
|
+
|
272
|
+
With v3, you can let all users log in without any intervention at all if their score is above some
|
273
|
+
threshold, and only show a v2 checkbox recaptcha challenge (fall back to v2) if it is below the
|
274
|
+
threshold:
|
275
|
+
|
276
|
+
```erb
|
277
|
+
…
|
278
|
+
<% if @show_checkbox_recaptcha %>
|
279
|
+
<%= recaptcha_tags %>
|
280
|
+
<% else %>
|
281
|
+
<%= recaptcha_v3(action: 'login', site_key: ENV['RECAPTCHA_SITE_KEY_V3']) %>
|
282
|
+
<% end %>
|
283
|
+
…
|
284
|
+
```
|
285
|
+
|
286
|
+
```ruby
|
287
|
+
# app/controllers/sessions_controller.rb
|
288
|
+
def create
|
289
|
+
success = verify_recaptcha(action: 'login', minimum_score: 0.5, secret_key: ENV['RECAPTCHA_SECRET_KEY_V3'])
|
290
|
+
checkbox_success = verify_recaptcha unless success
|
291
|
+
if success || checkbox_success
|
292
|
+
# Perform action
|
293
|
+
else
|
294
|
+
if !success
|
295
|
+
@show_checkbox_recaptcha = true
|
296
|
+
end
|
297
|
+
render 'new'
|
298
|
+
end
|
299
|
+
end
|
300
|
+
```
|
301
|
+
|
302
|
+
(You can also find this [example](demo/rails/app/controllers/v3_captchas_controller.rb) in the demo app.)
|
303
|
+
|
304
|
+
Another example:
|
305
|
+
|
306
|
+
```erb
|
307
|
+
<%= form_for @user do |f| %>
|
308
|
+
…
|
309
|
+
<%= recaptcha_v3(action: 'registration') %>
|
310
|
+
…
|
311
|
+
<% end %>
|
312
|
+
```
|
313
|
+
|
314
|
+
```ruby
|
315
|
+
# app/controllers/users_controller.rb
|
316
|
+
def create
|
317
|
+
@user = User.new(params[:user].permit(:name))
|
318
|
+
recaptcha_valid = verify_recaptcha(model: @user, action: 'registration')
|
319
|
+
if recaptcha_valid
|
320
|
+
if @user.save
|
321
|
+
redirect_to @user
|
322
|
+
else
|
323
|
+
render 'new'
|
324
|
+
end
|
325
|
+
else
|
326
|
+
# Score is below threshold, so user may be a bot. Show a challenge, require multi-factor
|
327
|
+
# authentication, or do something else.
|
328
|
+
render 'new'
|
329
|
+
end
|
330
|
+
end
|
331
|
+
```
|
332
|
+
|
333
|
+
|
334
|
+
### `recaptcha_v3`
|
335
|
+
|
336
|
+
Adds an inline script tag that calls `grecaptcha.execute` for the given `site_key` and `action` and
|
337
|
+
calls the `callback` with the resulting response token. You need to verify this token with
|
338
|
+
[`verify_recaptcha`](#verify_recaptcha-use-with-v3) in your controller in order to get the
|
339
|
+
[score](https://developers.google.com/recaptcha/docs/v3#score).
|
340
|
+
|
341
|
+
By default, this inserts a hidden `<input type="hidden" class="g-recaptcha-response">` tag. The
|
342
|
+
value of this input will automatically be set to the response token (by the default callback
|
343
|
+
function). This lets you include `recaptcha_v3` within a `<form>` tag and have it automatically
|
344
|
+
submit the token as part of the form submission.
|
345
|
+
|
346
|
+
Note: reCAPTCHA actually already adds its own hidden tag, like `<textarea
|
347
|
+
id="g-recaptcha-response-data-100000" name="g-recaptcha-response-data" class="g-recaptcha-response">`,
|
348
|
+
immediately ater the reCAPTCHA badge in the bottom right of the page — but since it is not inside of
|
349
|
+
any `<form>` element, and since it already passes the token to the callback, this hidden `textarea`
|
350
|
+
isn't helpful to us.
|
351
|
+
|
352
|
+
If you need to submit the response token to the server in a different way than via a regular form
|
353
|
+
submit, such as via [Ajax](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) or [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API),
|
354
|
+
then you can either:
|
355
|
+
1. just extract the token out of the hidden `<input>` or `<textarea>` (both of which will have a
|
356
|
+
predictable name/id), like `document.getElementById('g-recaptcha-response-data-my-action').value`, or
|
357
|
+
2. write and specify a custom `callback` function. You may also want to pass `element: false` if you
|
358
|
+
don't have a use for the hidden input element.
|
359
|
+
|
360
|
+
Note that you cannot submit/verify the same response token more than once or you will get a
|
361
|
+
`timeout-or-duplicate` error code. If you need reset the captcha and generate a new response token,
|
362
|
+
then you need to call `grecaptcha.execute(…)` again. This helper provides a JavaScript method (for
|
363
|
+
each action) named `executeRecaptchaFor{action}` to make this easier. That is the same method that
|
364
|
+
is invoked immediately. It simply calls `grecaptcha.execute` again and then calls the `callback`
|
365
|
+
function with the response token.
|
366
|
+
|
367
|
+
You will also get a `timeout-or-duplicate` error if too much time has passed between getting the
|
368
|
+
response token and verifying it. This can easily happen with large forms that take the user a couple
|
369
|
+
minutes to complete. Unlike v2, where you can use the `expired-callback` to be notified when the
|
370
|
+
response expries, v3 appears to provide no such callback. See also
|
371
|
+
[1](https://github.com/google/recaptcha/issues/281) and
|
372
|
+
[2](https://stackoverflow.com/questions/54437745/recaptcha-v3-how-to-deal-with-expired-token-after-idle).
|
373
|
+
|
374
|
+
To deal with this, it is recommended to call the "execute" in your form's submit handler (or
|
375
|
+
immediately before sending to the server to verify if not using a form) rather than using the
|
376
|
+
response token that gets generated when the page first loads. The `executeRecaptchaFor{action}`
|
377
|
+
function mentioned above can be used if you want it to invoke a callback, or the
|
378
|
+
`executeRecaptchaFor{action}Async` variant if you want a `Promise` that you can `await`. See
|
379
|
+
[demo/rails/app/views/v3_captchas/index.html.erb](demo/rails/app/views/v3_captchas/index.html.erb)
|
380
|
+
for an example of this.
|
381
|
+
|
382
|
+
This helper is similar to the [`recaptcha_tags`](#recaptcha_tags)/[`invisible_recaptcha_tags`](#invisible_recaptcha_tags) helpers
|
383
|
+
but only accepts the following options:
|
384
|
+
|
385
|
+
| Option | Description |
|
386
|
+
|---------------------|-------------|
|
387
|
+
| `:site_key` | Override site API key |
|
388
|
+
| `:action` | The name of the [reCAPTCHA action](https://developers.google.com/recaptcha/docs/v3#actions). Actions may only contain alphanumeric characters and slashes, and must not be user-specific. |
|
389
|
+
| `:nonce` | Optional. Sets nonce attribute for script. Can be generated via `SecureRandom.base64(32)`. (default: `nil`) |
|
390
|
+
| `:callback` | Name of callback function to call with the token. When `element` is `:input`, this defaults to a function named `setInputWithRecaptchaResponseTokenFor#{sanitize_action(action)}` that sets the value of the hidden input to the token. |
|
391
|
+
| `:id` | Specify a unique `id` attribute for the `<input>` element if using `element: :input`. (default: `"g-recaptcha-response-data-"` + `action`) |
|
392
|
+
| `:name` | Specify a unique `name` attribute for the `<input>` element if using `element: :input`. (default: `g-recaptcha-response-data[action]`) |
|
393
|
+
| `:script` | Same as setting both `:inline_script` and `:external_script`. (default: `true`). |
|
394
|
+
| `:inline_script` | If `true`, adds an inline script tag that calls `grecaptcha.execute` for the given `site_key` and `action` and calls the `callback` with the resulting response token. Pass `false` if you want to handle calling `grecaptcha.execute` yourself. (default: `true`) |
|
395
|
+
| `:element` | The element to render, if any (default: `:input`)<br/>`:input`: Renders a hidden `<input type="hidden">` tag. The value of this will be set to the response token by the default `setInputWithRecaptchaResponseTokenFor{action}` callback.<br/>`false`: Doesn't render any tag. You'll have to add a custom callback that does something with the token. |
|
396
|
+
| `:turbolinks` | If `true`, calls the js function which executes reCAPTCHA after all the dependencies have been loaded. This cannot be used with the js param `:onload`. This makes reCAPTCHAv3 usable with turbolinks. |
|
397
|
+
|
398
|
+
[JavaScript resource (api.js) parameters](https://developers.google.com/recaptcha/docs/invisible#js_param):
|
399
|
+
|
400
|
+
| Option | Description |
|
401
|
+
|---------------------|-------------|
|
402
|
+
| `:onload` | Optional. The name of your callback function to be executed once all the dependencies have loaded. (See [explicit rendering](https://developers.google.com/recaptcha/docs/display#explicit_render))|
|
403
|
+
| `:external_script` | Set to `false` to avoid including a script tag for the external `api.js` resource. Useful when including multiple `recaptcha_tags` on the same page.
|
404
|
+
| `:script_async` | Set to `true` to load the external `api.js` resource asynchronously. (default: `false`) |
|
405
|
+
| `:script_defer` | Set to `true` to defer loading of external `api.js` until HTML documen has been parsed. (default: `false`) |
|
406
|
+
|
407
|
+
If using `element: :input`, any unrecognized options will be added as attributes on the generated
|
408
|
+
`<input>` element.
|
409
|
+
|
410
|
+
### `verify_recaptcha` (use with v3)
|
411
|
+
|
412
|
+
This works the same as for v2, except that you may pass an `action` and `minimum_score` if you wish
|
413
|
+
to validate that the action matches or that the score is above the given threshold, respectively.
|
414
|
+
|
415
|
+
```ruby
|
416
|
+
result = verify_recaptcha(action: 'action/name')
|
417
|
+
```
|
418
|
+
|
419
|
+
| Option | Description |
|
420
|
+
|------------------|-------------|
|
421
|
+
| `:action` | The name of the [reCAPTCHA action](https://developers.google.com/recaptcha/docs/v3#actions) that we are verifying. Set to `false` or `nil` to skip verifying that the action matches.
|
422
|
+
| `:minimum_score` | Provide a threshold to meet or exceed. Threshold should be a float between 0 and 1 which will be tested as `score >= minimum_score`. (Default: `nil`) |
|
423
|
+
|
424
|
+
### Multiple actions on the same page
|
425
|
+
|
426
|
+
According to https://developers.google.com/recaptcha/docs/v3#placement,
|
427
|
+
|
428
|
+
> Note: You can execute reCAPTCHA as many times as you'd like with different actions on the same page.
|
429
|
+
|
430
|
+
You will need to verify each action individually with separate call to `verify_recaptcha`.
|
431
|
+
|
432
|
+
```ruby
|
433
|
+
result_a = verify_recaptcha(action: 'a')
|
434
|
+
result_b = verify_recaptcha(action: 'b')
|
435
|
+
```
|
436
|
+
|
437
|
+
Because the response tokens for multiple actions may be submitted together in the same request, they
|
438
|
+
are passed as a hash under `params['g-recaptcha-response-data']` with the action as the key.
|
439
|
+
|
440
|
+
It is recommended to pass `external_script: false` on all but one of the calls to
|
441
|
+
`recaptcha` since you only need to include the script tag once for a given `site_key`.
|
442
|
+
|
443
|
+
## `recaptcha_reply`
|
444
|
+
|
445
|
+
After `verify_recaptcha` has been called, you can call `recaptcha_reply` to get the raw reply from recaptcha. This can allow you to get the exact score returned by recaptcha should you need it.
|
446
|
+
|
447
|
+
```ruby
|
448
|
+
if verify_recaptcha(action: 'login')
|
449
|
+
redirect_to @user
|
450
|
+
else
|
451
|
+
score = recaptcha_reply['score']
|
452
|
+
Rails.logger.warn("User #{@user.id} was denied login because of a recaptcha score of #{score}")
|
453
|
+
render 'new'
|
454
|
+
end
|
455
|
+
```
|
456
|
+
|
457
|
+
`recaptcha_reply` will return `nil` if the the reply was not yet fetched.
|
458
|
+
|
459
|
+
## I18n support
|
460
|
+
|
461
|
+
reCAPTCHA supports the I18n gem (it comes with English translations)
|
462
|
+
To override or add new languages, add to `config/locales/*.yml`
|
463
|
+
|
464
|
+
```yaml
|
465
|
+
# config/locales/en.yml
|
466
|
+
en:
|
467
|
+
recaptcha:
|
468
|
+
errors:
|
469
|
+
verification_failed: 'reCAPTCHA was incorrect, please try again.'
|
470
|
+
recaptcha_unreachable: 'reCAPTCHA verification server error, please try again.'
|
471
|
+
```
|
472
|
+
|
473
|
+
## Testing
|
474
|
+
|
475
|
+
By default, reCAPTCHA is skipped in "test" and "cucumber" env. To enable it during test:
|
476
|
+
|
477
|
+
```ruby
|
478
|
+
Recaptcha.configuration.skip_verify_env.delete("test")
|
479
|
+
```
|
480
|
+
|
481
|
+
## Alternative API key setup
|
482
|
+
|
483
|
+
### Recaptcha.configure
|
484
|
+
|
485
|
+
```ruby
|
486
|
+
# config/initializers/recaptcha.rb
|
487
|
+
Recaptcha.configure do |config|
|
488
|
+
config.site_key = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
|
489
|
+
config.secret_key = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
|
490
|
+
# Uncomment the following line if you are using a proxy server:
|
491
|
+
# config.proxy = 'http://myproxy.com.au:8080'
|
492
|
+
end
|
493
|
+
```
|
494
|
+
|
495
|
+
### Recaptcha.with_configuration
|
496
|
+
|
497
|
+
For temporary overwrites (not thread safe).
|
498
|
+
|
499
|
+
```ruby
|
500
|
+
Recaptcha.with_configuration(site_key: '12345') do
|
501
|
+
# Do stuff with the overwritten site_key.
|
502
|
+
end
|
503
|
+
```
|
504
|
+
|
505
|
+
### Per call
|
506
|
+
|
507
|
+
Pass in keys as options at runtime, for code base with multiple reCAPTCHA setups:
|
508
|
+
|
509
|
+
```ruby
|
510
|
+
recaptcha_tags site_key: '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
|
511
|
+
|
512
|
+
# and
|
513
|
+
|
514
|
+
verify_recaptcha secret_key: '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
|
515
|
+
```
|
516
|
+
|
517
|
+
## Misc
|
518
|
+
- Check out the [wiki](https://github.com/ambethia/recaptcha/wiki) and leave whatever you found valuable there.
|
519
|
+
- [Add multiple widgets to the same page](https://github.com/ambethia/recaptcha/wiki/Add-multiple-widgets-to-the-same-page)
|
520
|
+
- [Use Recaptcha with Devise](https://github.com/plataformatec/devise/wiki/How-To:-Use-Recaptcha-with-Devise)
|