Google reCAPTCHA for a Flask app

Google reCAPTCHA for a Flask app

It is trival to add Google reCAPTCHA to a Flask app. Google's description of reCAPTCHA is "Protect your website from spam and abuse while letting real people pass through with ease."

Credit: based entirely on Vitor Freitas' post
Authored date: 2018 March 08
Technologies: Python 2.7.13, Flask 0.10.1, Jinja2, reCAPTCHA V2

Go to https://www.google.com/recaptcha/admin and register your domain as a reCAPTCHA V2 site. Copy your site and secret keys. In the code examples below I use config variables GOOGLE_RECAPTCHA_SITE_KEY and GOOGLE_RECAPTCHA_SECRET_KEY. Adjust your configuration to use your own reCAPTCHA keys.

In your Jinja template add this to your <head>:

<script src='https://www.google.com/recaptcha/api.js'></script>


And add this to your Jinja template inside your form, e.g. your login or registration form:

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


Create a decorator function that you will use to decorate your view function(s):

import requests
from functools import wraps
from flask import flash, request
from config.settings import GOOGLE_RECAPTCHA_SECRET_KEY

def check_recaptcha(f):
    """
    Checks Google  reCAPTCHA.

    :param f: view function
    :return: Function
    """
    @wraps(f)
    def decorated_function(*args, **kwargs):
        request.recaptcha_is_valid = None

        if request.method == 'POST':
            data = {
                'secret': GOOGLE_RECAPTCHA_SECRET_KEY,
                'response': request.form.get('g-recaptcha-response'),
                'remoteip': request.access_route[0]
            }
            r = requests.post(
                "https://www.google.com/recaptcha/api/siteverify",
                data=data
            )
            result = r.json()

            if result['success']:
                request.recaptcha_is_valid = True
            else:
                request.recaptcha_is_valid = False
                flash('Invalid reCAPTCHA. Please try again.', 'error')

        return f(*args, **kwargs)

    return decorated_function


The last step is to decorate the view or views that you would like to use reCAPTCHA and test request.recaptcha_is_valid for a truthy value:

@user.route('/login', methods=['GET', 'POST'])
@check_recaptcha
def login():
    """User login."""

    if form.validate_on_submit() and request.recaptcha_is_valid:
        # login user...

    return render_template('user/login.jinja2', form=form)


That's it, done.

Names and numbers can make a football shirt feel linked to a particular player. Supporters looking at third-shirt colours can use FC Barcelona jersey for fanscamiseta del FC Barcelona para aficionados) as the exact subject of comparison. Home and away versions can serve different preferences while representing the same team.