Forums

Flask : CSRF verification failed

Hi guys,

I'm having trouble with Flask and the CSRF verification, here is the stackoverflow question :

http://stackoverflow.com/questions/31032656/flask-csrf-verification-failed

Someone can help me to disable it or to implement it please ?

Thanks.

As I understand it, Flask doesn't have CSRF protection by default, so it's hard to explain why you're seeing CSRF verification problems.

One explanation would be if your client is somehow sending the request to the wrong domain -- could it be that you're sending requests to www.pythonanywhere.com, instead of to amaurycoron.pythonanywhere.com?

The request is sent to amaurycoron.pythonanywhere.com :

[request setValue:@"https://amaurycoron.pythonanywhere.com" forHTTPHeaderField: @"Referer"];

And it's the good one because if I reload the web app it works for several hours or a day then the CSRF error come back.

If you need more information to help me feel free to ask, I don't know what to do maybe it's a simple mistake.

OK, so let's assume that the CSRF error is coming from your flask web app then -- the next thing to find out is where from? In your SO post there's some talk of WT-forms, but you say you're not using that? Can we identify what is implementing the CSRF protection?

then, to explain the fact that it works for a few hours after doing a reload, that's sounding like there's some kind of mismatch between the expiry times the server is setting on its csrf tokens, and the frequency with which the client is updating its tokens... so we'd have to dig into that and figure out what's what...

Did you ever get this resolved? I'm having the exact same problem.

I don't think it was. So just to make sure it really is the same -- you have a Flask app that works fine after it's been reloaded, but stops working after a few hours. Is that right? Are you using WTForms?

I have a flask app that handles POST requests from plivo, and everything works great after restarting. If I don't make any plivo requests for a day or so, they start to fail with the error below. After restarting my pythonanywhere server it works again. If I continue to make a request once a day or so, it seems to keep working.

<p>CSRF verification failed. Request aborted.</p> <p>You are seeing this message because this HTTPS site requires a 'Referer header' to be sent by your Web browser, but none was sent. This header is required for security reasons, to ensure that your browser is not being hijacked by third parties.</p> <p>If you have configured your browser to disable 'Referer' headers, please re-enable them, at least for this site, or for HTTPS connections, or for 'same-origin' requests.</p>

I am not using WTForms.

Also, I tried adding a script to reload the site every day using "touch /var/www/florisvb_pythonanywhere_com_wsgi.py" as a hack, but that doesn't seem to work.

what happens if you add a before_request hook to see what headers are being sent? if you log all the requests and the headers, you can see if plivo is making requests with the right header.

I added the following before_request code in my flask_app.py:

app = Flask(__name__)
app.debug = True

@app.before_request
def before_request():
    print 'REQUEST HEADERS'
    print request.headers

@app.route("/", methods=['GET','POST'])

On successfully sending a message from my phone to plivo and getting a response I get the following in the server log:

2016-01-19 16:34:31 X-Real-Ip: 54.XX.XX.XXX#015#012Content-Length: 172#015#012User-Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.35 Safari/535.1#015#012Connection: close#015#012Host: florisvb.pythonanywhere.com#015#012Accept: /#015#012X-Forwarded-For: 54.XX.XX.XXX#015#012X-Plivo-Signature: XXXXXXXXXXXXXXXXXXXXXXXXXXX=#015#012Content-Type: application/x-www-form-urlencoded#015#012Accept-Encoding: gzip, deflate#015#012#015

(the XXX's replace various numbers and letters)

On a failed message, I don't get anything printed to the server log, or the error log.

Did I put the before_request decorator in the right file (or should it be in the wsgi file?)?

Debugging this problem is obnoxious, as I have to wait 24 hours between restarting my python anywhere server before I can see what happens with a failed message.

I suspect that whatever's failing with the CSRF error is being triggered by the Flask framework before it lets you near the before_request handler, which is annoying.

Do you think you could try a test where you send the request from a desktop browser rather than from the phone? Then you should be able to get more information about the headers from your browser's debug console.

We've finally tracked this one down! We've just pushed a system patch that fixes the problem.

Here's what it was: if a web app was shut down for some reason (system reboot, certain kinds of glitch, excessive resource usage, maybe hibernation) then only a GET request would wake it up. POST requests, in particular, would be rejected with a CSRF error (generated by our code that's meant to start up the web app), and the app wouldn't be woken up. So if your app is one that processes mostly POST requests, you'd see this problem. This definitely seems to fit the issue as you describe it.

Our new code wakes up the app when a POST is received. One slight issue remains -- the first POST request that wakes it up will receive a "503 Service Unavailable" response with the "retry-after" header set to "5". If you handle this and do the retry, then the next request will work. We believe that browsers do that automatically, but unfortunately the requests library doesn't by default.

This morning's system update fixed this issue:

the first POST request that wakes it up will receive a "503 Service Unavailable" response with the "retry-after" header set to "5". If you handle this and do the retry, then the next request will work. We believe that browsers do that automatically, but unfortunately the requests library doesn't by default.

Now websites that are hibernated will start up normally, regardless of what kind of request comes in.