'Flask-wtf Recaptcha always returns "the response parameter is missing"

I am trying to implement Recaptcha 2 in a flask web form, however, my form always fails to validate when I have recaptcha enabled. To dig a little deeper I printed out the errors from recaptcha and I always get "the response parameter is missing". I have looked at the source code and it seems this error corresponds to "missing-input-response", however, I can see that the green tick appears when I click the button. Here are before and after images.

enter image description here

enter image description here

I have been searching the web for hours and can't find a reason why this is happening. Here is my flask code and my html.

flask:

import os
from flask import Flask, render_template
from flask_wtf import FlaskForm
from flask_wtf.recaptcha import RecaptchaField
from wtforms import StringField, SubmitField
from flask_wtf.file import FileField, FileRequired, FileAllowed
from wtforms.validators import DataRequired
from dotenv import load_dotenv

app = Flask(__name__)

# load env variables
load_dotenv(dotenv_path='app.env')
SECRET_KEY = os.getenv('CSRF_TOKEN')
app.config['SECRET_KEY'] = SECRET_KEY
app.config['RECAPTCHA_PUBLIC_KEY'] = ''
app.config['RECAPTCHA_PRIVATE_KEY'] = ''

class InputForm(FlaskForm):
    email = StringField('Email-Adresse', validators=[DataRequired()])
    postcode = StringField('Postleitzahl', validators=[DataRequired()])
    upload = FileField('Angebotsdatei', validators=[FileRequired(), FileAllowed(['png', 'jpg', 'pdf'], "Invalid file format")])
    recaptcha = RecaptchaField()
    submit = SubmitField('Starten')

@app.route('/', methods=['GET', 'POST'])
def index_2():
    email = None
    postcode = None
    upload = None
    form = InputForm()
    # validate form
    if form.validate_on_submit():
        email = form.email.data
        postcode = form.postcode.data
        upload = form.upload.data
        form.email.data = ''
        form.postcode.data = ''
        form.upload = ''
    return render_template(
        "index_2.html",
        email = email,
        postcode = postcode,
        upload = upload,
        form = form
        )

if __name__ == "__main__":
    app.run(debug=True, host='127.0.0.1', port=5000)

html:

{% extends 'base.html' %}

{% block content %}

<div class="container containerform pt-3">
    <div class="container">
        {% if email %}
        <p class="text-center">Thanks for submitting to submitting the form!</p>
        {% else %}
        <form method="POST" enctype="multipart/form-data">
            {{ form.hidden_tag() }}
            {{ form.email.label(
            class="form-label"
            ) }}
            {{ form.email(
            class="form-control"
            ) }}
            {{ form.postcode.label(
            class="form-label"
            ) }}
            {{ form.postcode(
            class="form-control"
            ) }}
            {{ form.upload.label(
            class="form-label"
            ) }}
            {{ form.upload(
            class="form-control"
            ) }}
    </div>
    <br>
    <div class="recapture-box">
        {% for error in form.recaptcha.errors %}
            {{ error }}
        {% endfor %}
        {{ form.recaptcha }}
    </div>
    <br>
    <div class="submit-button-form pb-4">
        {{ form.submit(
        class="btn btn-primary btn-form"
        ) }}
    </div>
    </form>

    {% endif %}
</div>


{% endblock %}

I would appreciate any pointers here.

UPDATE

I still haven't managed to fix the problem, however, the issue lies in validation. While I can click and run recaptcha, I am not able to store the validation from google, and hence my validation_on_submit() returns False.



Solution 1:[1]

I recommend you to review the explanation on this web page. You can use this instead of the if form.validate_on_submit():.

captcha_response = request.form['g-recaptcha-response']
if len(captcha_response) > 0:

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Freddy Mcloughlan