HaskellYesod

Google reCaptcha v2 Integration in Yesod

Posted on by 

Since bots are more and more present in the web, it's a good (and well known) practice to add captcha protection to forms. In this blog post we will discuss how to integrate Google reCaptcha v2 implementation in Yesod.

First of all, let's create an applicative form which will serve as our example. We will keep this kind of form very simple since it's the same for larger forms. Our use case will be a user sign-up, which is one of the most common use cases for bot protection. We want real people to sign up for our project and not scripted bots:

data SignupForm = SignupForm 
  { email :: Text
  , firstName :: Maybe Text
  , lastName :: Maybe Text
  }

Very simple, we just need an email address. First name and a last name are optional fields. Let's build this form in a Yesod typical (applicative) way:

buildForm :: Form SignupForm
buildForm = renderDivs $ SignupForm
  <$> areq textField "E-Mail" Nothing
  <*> aopt textField "First Name" Nothing
  <*> aopt textField "Last Name" Nothing

Our form does not apply any CSS specific styles (renderDivs). Now, how to add a captcha? We are very lucky because other people already had this question and solved it for us. With the package yesod-recaptcha2 we can easily use reCaptcha in out form. We just need to add the following code to our `Foundation.hs` file:

import Yesod.ReCaptcha2

instance YesodReCaptcha App where
    reCaptchaSiteKey = pure "<insert your site key here>"
    reCaptchaSecretKey = pure "<insert your secret key here>"
    reCaptchaLanguage = pure Nothing

This code is already prepared to take your specific site settings (site key and secret key). The library will send the secret key to google when requesting a captcha verification.

In our form we just need to add the Yesod.ReCaptcha2 module and append the captcha:

import Yesod.ReCaptcha2 (reCaptcha)

buildForm :: Form SignupForm
buildForm = renderDivs $ SignupForm
  <$> areq textField "E-Mail" Nothing
  <*> aopt textField "First Name" Nothing
  <*> aopt textField "Last Name" Nothing
  <* reCaptcha

That's enough to have a completely working form with captcha protection. If you would like to change the language of the captcha, you can do this in the Foundation file by changing the reCaptchaLanguage function to:

import Yesod.ReCaptcha2

instance YesodReCaptcha App where
    reCaptchaSiteKey = pure "<insert your site key here>"
    reCaptchaSecretKey = pure "<insert your secret key here>"
    reCaptchaLanguage = pure $ Just "ru"

If you have any questions or comments, please feel free to use the comment area below.