Git Product home page Git Product logo

recaptcha's Introduction

Recaptcha

Build Status Coverage Status Module Version Hex Docs Total Download License Last Updated

A simple Elixir package for implementing reCAPTCHA in Elixir applications.

Migration from 1.x

Breaking Changes

  1. Template functionality is now in a separate module: Recaptcha.Template. Please note: in future templating may move to a Phoenix specific package.
  2. verify API has changed, see the code for documentation of the new API.

Most other questions about 2.x should be answered by looking over the documentation and the code. Please raise an issue if you have any problems with migrating.

Installation

Add :recaptcha to your mix.exs dependencies:

  defp deps do
    [
      {:recaptcha, "~> 3.0"},
    ]
  end

List :recaptcha as an application dependency:

  def application do
    [
      extra_applications: [:recaptcha]
    ]
  end

Run mix do deps.get, compile

Config

By default the public and private keys are loaded via the RECAPTCHA_PUBLIC_KEY and RECAPTCHA_PRIVATE_KEY environment variables.

config :recaptcha,
  public_key: {:system, "RECAPTCHA_PUBLIC_KEY"},
  secret: {:system, "RECAPTCHA_PRIVATE_KEY"}

JSON Decoding

By default reCaptcha will use Jason to decode JSON responses, this can be changed as such:

config :recaptcha, :json_library, Poison

Usage

Render the Widget

Use raw (if you're using Phoenix.HTML) and Recaptcha.Template.display/1 methods to render the captcha widget.

For recaptcha with checkbox:

<form name="someform" method="post" action="/somewhere">
  ...
  <%= raw Recaptcha.Template.display %>
  ...
</form>

For invisible recaptcha:

<form name="someform" method="post" action="/somewhere">
  ...
  <%= raw Recaptcha.Template.display(size: "invisible") %>
</form>
  ...

To change the position of the invisible recaptcha, use an option badge. See https://developers.google.com/recaptcha/docs/invisible on the date-badge.

Since recaptcha loads JavaScript code asynchronously, you cannot immediately submit the captcha form. If you have logic that needs to know if the captcha code has already been loaded (for example disabling submit button until fully loaded), it is possible to pass in a JS-callback that will be called once the captcha has finished loading. This can be done as follows:

<form name="someform" method="post" action="/somewhere">
  ...
  <%= raw Recaptcha.Template.display(onload: "myOnLoadCallback") %>
</form>
  ...

And then in your JS code:

function myOnLoadCallback() {
  // perform extra actions here
}

display method accepts additional options as a keyword list, the options are:

Option Action Default
noscript Renders default noscript code provided by google false
public_key Sets key to the data-sitekey reCaptcha div attribute Public key from the config file
hl Sets the language of the reCaptcha en

Verify API

Recaptcha provides the verify/2 method. Below is an example using a Phoenix controller action:

def create(conn, params) do
  case Recaptcha.verify(params["g-recaptcha-response"]) do
    {:ok, response} -> do_something
    {:error, errors} -> handle_error
  end
end

verify method sends a POST request to the reCAPTCHA API and returns 2 possible values:

{:ok, %Recaptcha.Response{challenge_ts: timestamp, hostname: host}} -> The captcha is valid, see the documentation for more details.

{:error, errors} -> errors contains atomised versions of the errors returned by the API, See the error documentation for more details. Errors caused by timeouts in HTTPoison or Jason encoding are also returned as atoms. If the recaptcha request succeeds but the challenge is failed, a :challenge_failed error is returned.

verify method also accepts a keyword list as the third parameter with the following options:

Option Action Default
timeout Time to wait before timeout 5000 (ms)
secret Private key to send as a parameter of the API request Private key from the config file
remote_ip Optional. The user's IP address, used by reCaptcha no default

Testing

In order to test your endpoints you should set the secret key to the following value in order to receive a positive result from all queries to the Recaptcha engine.

config :recaptcha,
  secret: "6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe"

Setting up tests without network access can be done also. When configured as such a positive or negative result can be generated locally.

config :recaptcha,
  http_client: Recaptcha.Http.MockClient,
  secret: "6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe"


  {:ok, _details} = Recaptcha.verify("valid_response")

  {:error, _details} = Recaptcha.verify("invalid_response")

Contributing

Check out CONTRIBUTING.md if you want to help.

Copyright and License

Copyright (c) 2016 Samuel Seay

This library is released under the MIT License. See the LICENSE.md file for further details.

recaptcha's People

Contributors

denispeplin avatar hermanverschooten avatar jeffjewiss avatar jhonathas avatar kelostrada avatar kennyballou avatar kianmeng avatar lpedromachado avatar luc-tielen avatar maartenvanvliet avatar mynameisurl avatar ryan-senn avatar samueljseay avatar sobolevn avatar steveops avatar stwf avatar szysza avatar woylie avatar zazaian 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  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

recaptcha's Issues

Dependencies resolution error

I am upgrading from the first version of recaptcha, faced this issue:

[12:43:19] sobolev :: MacBook-Pro-Nikita ➜ Documents/elixir/elixir_lang_moscow ‹master› » mix deps.get
A new Hex version is available (0.13.0), please update with mix local.hex
Running dependency resolution

Failed to use "poison" (versions 1.0.0, 1.0.1, 1.0.2, 1.0.3, 1.1.0, 1.1.1, 1.2.0, 1.2.1, 1.3.0, 1.3.1, 1.4.0, 2.0.0, 2.0.1, 2.1.0, 2.2.0) because
arc (version 0.5.3) requires ~> 1.2 or ~> 2.0
dogma (version 0.1.7) requires >= 1.0.0
ecto (version 1.1.9) requires ~> 1.0 or ~> 2.0
ex_aws (version 0.4.19) requires ~> 1.2 or ~> 2.0
guardian (version 0.10.1) requires ~> 1.5
phoenix (version 1.1.6) requires ~> 1.5 or ~> 2.0
phoenix_ecto (version 2.0.2) requires ~> 1.3 or ~> 2.0
swoosh (version 0.4.0) requires ~> 1.5 or ~> 2.0

Failed to use "poison" (versions 1.5.0 to 1.5.2) because
arc (version 0.5.3) requires ~> 1.2 or ~> 2.0
dogma (version 0.1.7) requires >= 1.0.0
ecto (version 1.1.9) requires ~> 1.0 or ~> 2.0
ex_aws (version 0.4.19) requires ~> 1.2 or ~> 2.0
guardian (version 0.10.1) requires ~> 1.5
phoenix (version 1.1.6) requires ~> 1.5 or ~> 2.0
phoenix_ecto (version 2.0.2) requires ~> 1.3 or ~> 2.0
#! recaptcha (version 2.0.0) requires ~> 2.0
swoosh (version 0.4.0) requires ~> 1.5 or ~> 2.0

** (Mix) Hex dependency resolution failed, relax the version requirements of your dependencies or unlock them (by using mix deps.update or mix deps.unlock)

Poison version from the mix.lock:

"poison": {:hex, :poison, "1.5.2", "560bdfb7449e3ddd23a096929fb9fc2122f709bcc758b2d5d5a5c7d0ea848910", [:mix], []},

I guess this issue can be solved by editing poison dependency string to something like: {:poison, "~> 1.5 or ~> 2.0"},

Suggested Improvements

Hi,

Picked up this lib today to use and its great thanks for putting it together 😄

I was just wondering if perhaps you'd be interested in a PR with adjustments to the API, that in my mind sit a little closer to Elixir idioms.

A couple things I'd love to change:

  1. It'd be great if there were a verify! and a verify with verify! being the only method call that raises an exception. I don't really ever want to raise exceptions, but rather receive errors from the API and deal with them.
  2. I'd love if the return from verify was a bit more idiomatic returning a tuple like:
# success, with response being the json returned by googles api
{:ok, response} 

# error, contains all the specific error messages, let the user of the API handle them as they wish
{:error, errors}

thoughts?

cannot convert the given list to string

I modified my config.exs, my template file, and controller as instructed in the README and got the following errors:

    ** (ArgumentError) cannot convert the given list to a string.

To be converted to a string, a list must either be empty or only
contain the following elements:

  * strings
  * integers representing Unicode code points
  * a list containing one of these three elements

Please check the given list or call inspect/1 to get the list representation, got:

[:missing_input_response, :invalid_input_secret]

Additionally, why does the library not use the Phoenix native format for HTML?
<form name="someform" method="post" action="/somewhere"> instead of <%= form_for...

Release new version to hex.pm

Hi,

Could you increase the version (2.3?) in mix.exs + release to hex.pm?
Currently we depend on a fork of this library, would be nice if we could just use hex.
Thanks!

Add tests

Hey, thanks for the package!

But for me it's kind of suspicious to use a package without any tests. Maybe you need any help implementing them?

Making validation call configurable

Things I suggest:

  1. Use :hackney as a default HTTP-server
  2. Create new macro to handle the verifications (Recaptcha.Validator)
  3. Rewrite verify/2 to works with tuples {:ok, _} and {:error, _} and not with bang versions.
  4. Create an overridable function to be used like so:
defmodule MyApp.RecaptchaValidator do
  use Recaptcha.Validator

  def verify_request(verify_url, body, headers) do
    # Old signature:
    # HTTPoison.post!(@site_verify_url, body, headers, timeout: timeout)
    {:ok, response} = MyHttpServer.post(verify_url, body, headers)
  end
end

And then test all the things.

What do you think of it?

Error generated by MockClient isn't the same as the real one

Normally an "invalid-input-response" error from reCAPTCHA causes the verify function to return {:error, [:invalid_input_response]}. However, when using the feature of the MockClient where the response "invalid_response" intentionally causes an error, the return is instead {:error, [:"invalid-input-response"]}. If you have different handling for different reCAPTCHA errors, the consequence is that you have to match on the "fake error" separately from the real one.

Release 2.2.2

Hi, could you please release master as v2.2.2?

I'm currently having trouble installing this package due to #37, which has been resolved, but not yet released. Thanks!

protocol String.Chars not implemented for

Phoenix v1.3.0

for Recaptcha.verify...

exception:
protocol String.Chars not implemented for {:system, "secret_key"}
...

config should be ?

config :recaptcha,
public_key: "public_key",
secret: "secret_key"

recaptcha (version 3.0.0) requires ~> 3.1.0 or ~> 2.2.0 or ~> 1.5.2

Does this project need a release bump? I'm in a dependency "situation" because of the version of Poison that it requires, but looking in master, it doesn't appear to require Poison at all. This leads me to believe that might need a new release that drops the dependency on Poison.

Bump dependencies

It seems that recaptcha is using a fairly outdated version of poison. It would be really good if it could support more recent versions, because recent versions of dependencies like poison are used in many other packages, making it a hard choice to make to pick recaptcha.

Config Outdated

The config doc is outdated.
verify/2 works when giving option but does not take value from environmental variable.

Mock client doesn't work with `remote_ip`

When calling Recaptcha.verify with the remote_ip option, Recaptcha.Http.MockClient passes the request through to the real HTTP client (due to exact matching on the query params), so even a verification using "invalid_response" is always successful.

Json parser issue in version 3.0.0

I don't know exactly how it is happening yet, but on version 3.0.0 when json parser was updated to Jason, it doesn't seem to be picked up by the configuration, as i get this error:

 ** (UndefinedFunctionError) function nil.decode/1 is undefined
        nil.decode("{\n  \"success\": false,\n  \"error-codes\": [\n    \"timeout-or-duplicate\"\n  ]\n}")
        (recaptcha 3.0.0) lib/recaptcha/http.ex:48: Recaptcha.Http.request_verification/2
        (recaptcha 3.0.0) lib/recaptcha.ex:31: Recaptcha.verify/2

I'm able to run it without issues if I still add this line in my config file as it was previously recommended:
config :recaptcha, :json_library, Jason

Mock tests

First of all, thanks for the incredible library!

What is the best way to mock the lib in order to prevent the requests to google and have an precise behaviour? What are your suggestions? Thanks in advance.

Elixir 1.4 version support

I am pretty sure that it is going to be fine, but we need to ensure that it is working.

I suggest adding 1.4 to build-matrix in .travis.yml.

function nil.decode/1 is undefined

`json = Application.get_env(:recaptcha, :json_library)

result =

  with {:ok, response} <-

         HTTPoison.post(url, body, @headers, timeout: timeout),

       {:ok, data} <- json.decode(response.body) do

    {:ok, data}

  end

case result do

  {:ok, data} -> {:ok, data}`

Missing several Meta files in repository

I guess the working process may be improved if we would provide two extra files for our potential contributors. I am talking about:

  • changelog: so it would be clear what have changed
  • contributing.md: so it would be clear how to contribute to the repo (how to run tests and style-checks)

What do you think?

HTML.Phoenix.raw/1 not converting string to html correctly.

Hello, I have the following in my form.

<%= raw App.Recaptcha.Template.generate_template(@options) %>

This is what my template.html.eex looks like. This is what it looks like in the DOM. Any ideas why everything inside <noscript> is in a string?
Screen Shot 2020-09-24 at 7 49 39 PM

I've been working on this for a few days but I am out of luck. Any insight is appreciated.

Getting :ok back from Recaptcha.verify("invalid_response")

I have my test environment set up as described in the readme:

config :recaptcha,
  http_client: Recaptcha.Http.MockClient,
  secret: "6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe"

but I am getting an :ok tuple back from Recaptcha.verify("invalid_response") instead of an :error tuple:

$ MIX_ENV=test iex -S mix
Erlang/OTP 22 [erts-10.7.2.3] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [hipe]

Interactive Elixir (1.10.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Recaptcha.verify("invalid_response")
{:ok,
 %Recaptcha.Response{
   challenge_ts: "2020-10-07T19:01:22Z",
   hostname: "testkey.google.com"
 }}

Add support for Recaptcha v3

As mentioned in #55 recaptcha v3 has quite a few differences in implementation.

Also sort of related there is an enterprise mode as well, so I think it would make sense to build some simple configuration options to switch between these new modes.

Doesn't work with Phoenix Live View

I'm struggling to get this to work with Phoenix Live View.

The live view submit handler is called before the recaptcha javascript can go through its sequence and update the form with a g-recaptcha-response field.


Here I'm inspecting the form generated with a phx_submit callback. The second handler is recaptcha's code, but the form has already been handled via live view by the time it gets to recaptchaCallback

I'm looking into live view's JS interoperability features but I'm not seeing a hook function that can be inserted before the submit event.

Actually it doesn't ever seem to be calling recaptchaCallback - I'm not sure how JS scope works if elements containing functions are replaced in the DOM. I see that the form value is being assigned to the window scope so maybe that's getting overwritten somehow as part of the live view render sequence.

I expect I'll be updating this thread with my findings as I go. Sorry not to have a test case for you.

Support for reCAPTCHA v3?

I'm assuming the version bump to 3.0.0 doesn't mean support for reCAPTCHA v3. I thought I'd ask in case the repo description on Github just wasn't updated. I see no specific mention of reCAPTCHA v3 in the README or docs and the template.html.eex file seems to look like v2 stuff.

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.