Tech Monger

Programming, Web Development and Computer Science.

Skip to main content| Skip to information by topic

How to add ReCaptcha to Flask App without Extension

In this article we will learn to integrate Google ReCaptcha into flask web application without using any flask extension to prevent bots from submitting spam.

Traditionally web applications used CAPTCHA containing image with some problem which human could solve but no automated bot can solve. In modern applications this can be achieved by using third party API like Google ReCaptcha.

How Google ReCaptcha API works ?

  1. When you register for recaptcha it provides you two keys.

    • Site Key : For Client Side Integration
    • Secret Key : For Server Side Integration
  2. Whenever user submits a form configured with ReCaptcha it contains payload with name g-recaptcha-response.

  3. Upon submitting form your server collects g-recaptcha-response and sends it to google server along with Secret Key to make sure submitted form was from human and not from bot.

  4. Google server check g-recaptcha-response sent by you and returns back value suggesting whether form submission is from human or bot .

Registering for ReCaptcha

Before we begin with actual code I assume that you have registered for Google ReCaptcha and have Site Key and Secret Key for your domain.

To test application locally add localhost into the domain name while registering like below.

Google ReCaptcha Registration with localhost

Implementing ReCaptcha with python and flask

We will create contact form which is most common use case for using flask and recaptcha. Form will allow user to submit name, email and message. At the end of the tutorial working code will be pushed on github for easier access.

  1. Client side Implementation
  2. For client side implementation we will include two elements into html

    1. ReCaptcha Javascript Code Inside head tag
      <script src="https://www.google.com/recaptcha/api.js"></script>
      
    2. div to render ReCaptcha Control inside form
      <div class="g-recaptcha" data-sitekey=""></div>
      
    3. For client side we will create simple form with 4 fields. (Name, Email Address, Message and ReCaptcha.

      Name : Email: Message: Security Check
      Note that how we have included sitekey generated during ReCaptcha registration inside div to render ReCaptcha. <div class="g-recaptcha" data-sitekey=""></div>

      Instead of hardcoding, sitekey you can render it by passing it to view with jinja2 from server side python code.

      <div class="g-recaptcha" data-sitekey="{{ sitekey }}"></div>
      

      After rendering example form will look like this.

      HTML Form with ReCaptcha
      Form with ReCaptcha using Python Flask

  3. Server Side Integration
    1. Accept form values with g-recaptcha-response

      Once user has submitted the form by completing ReCaptcha challenge form will get additional field from ReCaptcha under name g-recaptcha-response. Accept it along with other fields with flask contact route.

      @app.route("/contact/", methods=["GET", "POST"])
      def contact():
          if request.method == "POST":
              name = request.form['name']
              email = request.form['email']
              msg = request.form['message']
              captcha_response = request.form['g-recaptcha-response']
      
    2. Verify captcha_response from ReCaptcha Server

      To check submitted token under captcha_response it needs to be send to google server with payload response. We will use python requests. Server will check captcha_response and respond json object response_text.

      response_text will have key success containing value true if request is valid (from human) and false if it's invalid. We will implement this by defining is_human function in python.

      Note that we need to pass Secret Key generated during registration under payload secret to ReCaptcha server while verifying captcha_response.

      def is_human(captcha_response):
          """ Validating recaptcha response from google server
              Returns True captcha test passed for submitted form else returns False.
          """
          secret = "2PmehhhhsdhsjHGOnjdnsjkfnkjsdn56HDHFjhjh"
          payload = {'response':captcha_response, 'secret':secret}
          response = requests.post("https://www.google.com/recaptcha/api/siteverify", payload)
          response_text = json.loads(response.text)
          return response_text['success']
      
    3. Process Request

      If is_human returns True then we will process contact request else we will show message saying Bots are not allowed !

      @app.route("/contact/", methods=["GET", "POST"])
      def contact():
          """ Renders contact form on get and processes it on post. """
          
          sitekey = "your-site-key-here"
      
          if request.method == "POST":
              name = request.form['name']
              email = request.form['email']
              msg = request.form['message']
              captcha_response = request.form['g-recaptcha-response']
              
              if is_human(captcha_response):
                  # Process request here
                  status = "Detail submitted successfully."
              else:
                   # Log invalid attempts
                  status = "Sorry ! Bots are not allowed."
      
              flash(status)
              return redirect(url_for('contact'))
      
          return render_template("contact.html", sitekey=sitekey)
      
      
    4. Code

      Working code for the flask contact form has been posted on gihub. Please configure site-key and secret key into contact_form.py before running the application.

Tagged Under : Flask Python Web