Forums

CSRF Flask 500 Internal Server Error

Hi, I've been tearing my hair out trying to make this work. I have a contact form on my site that was working, but now throws a 500 error. The error log says it's a CSRF key issue, but I have a CSRF key set. I'm not sure why this started, but I think it's because I might have updated either WTForms or flask_wtf. I do reload the server after every update.

2019-02-16 04:58:57,187: Exception on /contact [GET] Traceback (most recent call last): File "/home/reclaimernz/.virtualenvs/my-virtualenv/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app response = self.full_dispatch_request() File "/home/reclaimernz/.virtualenvs/my-virtualenv/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request rv = self.handle_user_exception(e) File "/home/reclaimernz/.virtualenvs/my-virtualenv/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception reraise(exc_type, exc_value, tb) File "/home/reclaimernz/.virtualenvs/my-virtualenv/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise raise value File "/home/reclaimernz/.virtualenvs/my-virtualenv/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request rv = self.dispatch_request() File "/home/reclaimernz/.virtualenvs/my-virtualenv/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request return self.view_functionsrule.endpoint File "/home/reclaimernz/englishwithmark/app.py", line 47, in contact form = ContactForm() File "/home/reclaimernz/.virtualenvs/my-virtualenv/lib/python3.6/site-packages/wtforms/form.py", line 212, in call return type.call(cls, args, kwargs) File "/home/reclaimernz/.virtualenvs/my-virtualenv/lib/python3.6/site-packages/flask_wtf/form.py", line 88, in init super(FlaskForm, self).init(formdata=formdata, kwargs) File "/home/reclaimernz/.virtualenvs/my-virtualenv/lib/python3.6/site-packages/wtforms/form.py", line 278, in init self.process(formdata, obj, data=data, *kwargs) File "/home/reclaimernz/.virtualenvs/my-virtualenv/lib/python3.6/site-packages/wtforms/form.py", line 132, in process field.process(formdata) File "/home/reclaimernz/.virtualenvs/my-virtualenv/lib/python3.6/site-packages/wtforms/csrf/core.py", line 43, in process self.current_token = self.csrf_impl.generate_csrf_token(self) File "/home/reclaimernz/.virtualenvs/my-virtualenv/lib/python3.6/site-packages/flask_wtf/csrf.py", line 134, in generate_csrf_token token_key=self.meta.csrf_field_name File "/home/reclaimernz/.virtualenvs/my-virtualenv/lib/python3.6/site-packages/flask_wtf/csrf.py", line 35, in generate_csrf message='A secret key is required to use CSRF.' File "/home/reclaimernz/.virtualenvs/my-virtualenv/lib/python3.6/site-packages/flask_wtf/csrf.py", line 121, in _get_config raise KeyError(message) KeyError: 'A secret key is required to use CSRF.'

The relevant code is:

from flask import Flask, render_template, flash, redirect, url_for, session, logging, request
from flask_wtf import FlaskForm
from flask_wtf.csrf import CSRFProtect
from wtforms import TextField, TextAreaField, StringField, SubmitField
from wtforms.validators import DataRequired, Email


app = Flask(__name__, static_folder="static", static_url_path='')
app.url_map.strict_slashes = False
csrf = CSRFProtect(app)


# Contact
@app.route("/contact", methods=['GET','POST'])
def contact():
    form = ContactForm()

if request.method == 'POST':
    if form.validate() == False:
        return render_template('contact.html', form=form)
    else:
        msg = Message(form.subject.data, sender='sender', recipients=['recipient'])
        msg.body =  """From: %s <%s> %s""" % (form.name.data, form.email.data, form.message.data)
        mail.send(msg)
        return render_template('contact.html', success=True)

elif request.method == 'GET':
    return render_template("contact.html", form=form)

class ContactForm(FlaskForm):
name = StringField("Name",validators=[DataRequired()], render_kw={"placeholder": "Name"})

email = StringField("Email", validators=[Email()], render_kw={"placeholder": "Email"})

subject = StringField("Subject",validators=[DataRequired()], render_kw={"placeholder": "Subject"})

message = TextAreaField("Message",validators=[DataRequired()], render_kw={"placeholder": "Message"})

submit = SubmitField("Submit")

if __name__ == "__main__":
app.config['SECRET_KEY'] = "secretkey"
app.config['WTF_CSRF_SECRET_KEY'] = "secretkey"
csrf.init_app(app)
app.run()

And the form fields in my contact.html file are:

<form action="{{ url_for('contact') }}" method="POST">
{{ form.csrf_token() }}

{{ form.name }}

{{ form.email }}

{{ form.subject }}

{{ form.message }}

{{ form.submit }}

</form>

I'd appreciate any help and thanks in advance :)

You're only setting your secret key inside the

if __name__ == "__main__":

block, which isn't executed on production servers. You should move these three lines

app.config['SECRET_KEY'] = "secretkey"
app.config['WTF_CSRF_SECRET_KEY'] = "secretkey"
csrf.init_app(app)

up so that they are just after the line

csrf = CSRFProtect(app)

Thanks very much for your help! It works now :D

Great! Glad we could help.