Giter Club home page Giter Club logo

new_google_recaptcha's Introduction

Google Recaptcha v3 + Rails

Build Status RailsJazz https://www.patreon.com/igorkasyanchuk Listed on OpenSource-Heroes.com

Integrate Google Recaptcha v3 with Rails app.

Google Recaptcha console: https://www.google.com/recaptcha/admin#list

Recaptcha v3 documentation: https://developers.google.com/recaptcha/docs/v3

Usage

  • Open https://www.google.com/recaptcha/admin#list
  • register a new site
  • copy site_key and secret_key and put into config/initializers/new_google_recaptcha.rb
  • optionally, change the minimum_score in the initializer to a preferred float value (from 0.0 to 1.0)
  • in layout:
    <head>
      ...
      <%= yield :recaptcha_js %>
    </head>
  • in view where you for example you have a form:
    <%= content_for :recaptcha_js do %>
      <%= include_recaptcha_js %>
    <% end %>
    <form ...>
      <%#= 'checkout' is action name to be verified later %>
      <%= recaptcha_action('checkout') %>
    </form>
  • in controller:
    def create
      @post = Post.new(post_params)
      if NewGoogleRecaptcha.human?(
          params[:new_google_recaptcha_token],
          "checkout",
          NewGoogleRecaptcha.minimum_score,
          @post
        ) && @post.save
        redirect_to @post, notice: 'Post was successfully created.'
      else
        render :new
      end
    end
    
    
    # or
    # if you need to capture a humanity `score` from Google
    # before you need to add a column for example `humanity_score` (type: float) where this score will be saved.
    
    
    def create
      @post = Post.new(post_params)
      humanity_details =
        NewGoogleRecaptcha.get_humanity_detailed(
          params[:new_google_recaptcha_token],
          "checkout",
          NewGoogleRecaptcha.minimum_score,
          @post
        )
    
      @post.humanity_score = humanity_details[:score]
    
      if humanity_details[:is_human] && @post.save
        redirect_to @post, notice: 'Post was successfully created.'
      else
        render :new
      end
    end

There are two mandatory arguments for human? method:

  • token - token valid for your site
  • action - the action name for this request (the gem checks if it is the same as the name used with the token, otherwise a hacker could replace it on frontend to some another action used, but with lower score requirement and thus pass the verification)

You can verify recaptcha without using these arguments:

  • minimum_score - defaults to value set in the initializer (reCAPTCHA recommends using 0.5 as default)
  • model - defaults to nil which will result in not adding an error to model; any custom failure handling is applicable here

like this:

  NewGoogleRecaptcha.human?(params[:new_google_recaptcha_token], "checkout")

Saving humanity score from Google in your model

get_humanity_detailed method acts like human? method, the only difference is that it returns following hash with three key-value pairs:

  • is_human - whether actor is a human or not (same as result of human? method)
  • score - actual humanity score from recaptcha response
  • model - model which you trying to save

It could be handy if you want to store score in db or put it into logs or smth else. Real example is above in the code samples.

Add to your navigation links data-turbolinks="false" to make it works with turbolinks.

Installation

gem 'new_google_recaptcha'

And then execute:

$ bundle

And then run:

$ rails generate new_google_recaptcha initializer

And edit new_google_recaptcha.rb and enter your site_key and secret_key.

API

NewGoogleRecaptcha.human?(token, model) or NewGoogleRecaptcha.get_humanity_detailed(token, model) in contoller

  • token is received from google, must be sent to backend
  • model optional parameter. if you want to add error to model.

<%= include_recaptcha_js %> in layout (by using yield)

Include Google Recaptcha v3 JS into your Rails app. In head, right before </head>.

<%= recaptcha_action(action_name) %> in view

Action where recaptcha action was executed. Actions could be viewed in Admin console. More docs: https://developers.google.com/recaptcha/docs/v3. Action name could be "comments", "checkout", etc. Put any name and check scores in console.

How to add to the Devise

Generate Devise controllers and views, and edit "create" method.

class Users::RegistrationsController < Devise::RegistrationsController
...
  def create
    build_resource(sign_up_params)

    NewGoogleRecaptcha.human?(
      params[:new_google_recaptcha_token],
      "user",
      NewGoogleRecaptcha.minimum_score,
      resource) && resource.save

    yield resource if block_given?
    if resource.persisted?
      if resource.active_for_authentication?
        set_flash_message! :notice, :signed_up
        sign_up(resource_name, resource)
        respond_with resource, location: after_sign_up_path_for(resource)
      else
        set_flash_message! :notice, :"signed_up_but_#{resource.inactive_message}"
        expire_data_after_sign_in!
        respond_with resource, location: after_inactive_sign_up_path_for(resource)
      end
    else
      clean_up_passwords resource
      set_minimum_password_length
      respond_with resource
    end
  end

How to use in test or specs

At the end of the spec/rails_helper.rb put:

module NewGoogleRecaptcha
  def self.human?(*attrs)
    true
  end
end

Tests are located in specs folder and test/dummy/tests folder.

I18n support

reCAPTCHA passes one types of error explanation to a linked model. It will use the I18n gem to translate the default error message if I18n is available. To customize the messages to your locale, add these keys to your I18n backend:

new_google_recaptcha.errors.verification_human error message displayed when it is something like a robot, or a suspicious action

Also you can translate API response errors to human friendly by adding translations to the locale (config/locales/en.yml):

en:
  new_google_recaptcha:
    errors:
      verification_human: 'Fail'

Badge position

NewGoogleRecaptcha allows you to render badge in different positions

    <%= include_recaptcha_js badge: "bottomleft" %>

Three of existing badge values are bottomright, bottomleft and inline. 'inline' lets you position it with CSS.

TODO

  • check everything works with turbolinks
  • allow custom ID for input
  • more tests
  • handle exceptions with timeouts, json is not parsed
  • add support for non-Rails apps
  • add support for older Rails (should be easy since code is very simple)

Contributors

You are welcome to contribute.

License

The gem is available as open source under the terms of the MIT License.

new_google_recaptcha's People

Contributors

adelnabiullin avatar dachinat avatar edugonch avatar gilcierweb avatar igorkasyanchuk avatar rorelessar avatar rubyconvict avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

new_google_recaptcha's Issues

Confirm humanize after fail

Almost always by first signup - you will have 0.0 humanize score, and only after 2-3 times repeating - your humanize will increase. But i want to confirm i'm a human after first signup fail lol by click on images, how to do that?

Captcha displays on page load

It is possible I'm misunderstanding the instructions but the recaptcha form displays as soon as the form page loads. I have followed the config setup in the readme and <%= recaptcha_action('contact') %> appears in the <form>. My controller action is not 'create' as in the instructions but 'contact' instead. This action exists in the base controller.

I expect the recaptcha to display only after user has clicked to submit form.

Several pages with reCaptcha

I use reCaptcha v3. On the website I have 2 pages with form, that include reCaptcha. When I visit the first page - reCaptcha works fine, but when I visit the second one by clicking the menu link (current location is the first page that contains the form with reCaptcha), recaptcha doesn't work. When I inspect the page, the reCaptcha's token input's value is absent. When I visit a page without the form, and then visit a page with form, reCaptcha works fine, the hidden field's value contains the token.

This is how I include the script on the page:

<%= content_for :recaptcha_js do %>
  <%= raw %Q{
        <script src="https://www.google.com/recaptcha/api.js?render=#{ENV['RECAPTCHA_SITE_KEY']}" data-turbolinks-track="reload"></script>
      } %>
<% end %>

Any ideas how to make it work? Thanks ahead.

Disable new_google_recaptcha for test cases

error:

  WebMock::NetConnectNotAllowedError:
       Real HTTP connections are disabled. Unregistered request: GET https://www.google.com/recaptcha/api/siteverify?response=&secret=6LfHB7kUAAAAAHTFLRZDh6o23ICu86HbLUXB_Ric with headers {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Host'=>'www.google.com', 'User-Agent'=>'Ruby'}
     
       You can stub this request with the following snippet:
     
       stub_request(:get, "https://www.google.com/recaptcha/api/siteverify?response=&secret=6LfHB7kUAAAAAHTFLRZDh6o23ICu86HbLUXB_Ric").
         with(headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Host'=>'www.google.com', 'User-Agent'=>'Ruby'}).
         to_return(status: 200, body: "", headers: {})

How to add this in rails_helper.rb

module NewGoogleRecaptcha
      def self.human?(*attrs)
        true
      end
end

Too huge requests amount (recaptcha admin console)

Sorry for posting it here, but I cannot find google's support for developers
And may it will be useful for others who use recaptcha v3, too

Question: I integrated the gem and after first day of usage on production I have following:

Снимок экрана 2019-03-27 в 12 54 21

As you can see there are 4k+ requests in one day, but actually form was submitted only 3 times that day

It's very strange

I have 2 ideas:

  1. Google Analytics integrated as well (we use it for several years now), so maybe google just collected (GA) users behavior around the form where I integrated recaptcha and now shows it to me like it was yesterday
  2. Recaptha that I integrated into form sends requests to google not only when user submits the form, but it does it permanently with some delay and with high frequency

Could you please explain its behavior please if you know
Thanks in advance

Gem will not fully work with reCAPTCHA v3

Hello.

Thanks for gem, but after investigation I found it really will not work as expected and only check that reCAPTCHA works inside rails application. Why?

reCAPTCHA v3 returns a score for each request without user friction. The score is based on interactions with your site and enables you to take an appropriate action for your site

Next move to "Site Verify Response" inside doc:

{
  "success": true|false,      // whether this request was a valid reCAPTCHA token for your site
  "score": number             // the score for this request (0.0 - 1.0)
  "action": string            // the action name for this request (important to verify)
  "challenge_ts": timestamp,  // timestamp of the challenge load (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)
  "hostname": string,         // the hostname of the site where the reCAPTCHA was solved
  "error-codes": [...]        // optional
}

So as we can see, success only mean that token is valid, nothing more. To check bot or human we need to check score, which between 0 and 1. Developer need to adjust inside codebase check for this score based on action (for example valid?(token, scope)).

Also we should check action, so hacker will not replace on frontend action to some another with lower score and pass verification.

Right now https://github.com/igorkasyanchuk/new_google_recaptcha/blob/master/lib/new_google_recaptcha/validator.rb#L9 only check that token is valid. Library will pass everyone with valid token.

Hope this will help to improve gem.

Display settings

Would be nice to be able to show reCaptcha logo on-page or on left side of screen, not only on the right side.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.