Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask : CSRF verification failed

I am sending a POST request from an iOS client

-(void)loadFavorite:(NSArray*)favorites{

    //data and url preparation

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
    [request setHTTPMethod:@"POST"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [request setValue:@"https://example.com" forHTTPHeaderField: @"Referer"];

    [request setValue:[NSString stringWithFormat:@"%tu", [requestData length]] forHTTPHeaderField:@"Content-Length"];
    [request setHTTPBody: requestData];

    if ([Tools isNetWorkConnectionAvailable]) {
        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
            //response handle
    }
}

Here is the response :

<div id="summary">
  <h1>Forbidden <span>(403)</span></h1>
  <p>CSRF verification failed. Request aborted.</p>
</div>

I'm using Flask framework and pythonanywhere for hosting.

It works fine when I reload the python script but after few hours/days the CSRF verification failed error reappear.

Even if I try to disable the CSRF verification in my app.py with :

app.config['WTF_CSRF_CHECK_DEFAULT'] = False

App.py script :

//some import error handlers ...

app = Flask(__name__)
app.config['WTF_CSRF_CHECK_DEFAULT'] = False

@app.route('/api/favorites', methods=['POST'])
def get_favorites_beaches():
    if not request.json or not 'favorite' in request.json:
        abort(400)
    //data process

if __name__ == '__main__':
    app.run(host='0.0.0.0',debug=True)

How can I implement the CSRF verification correctly or how to disable it ?

like image 475
Boris-V Avatar asked Jun 24 '15 16:06

Boris-V


1 Answers

PythonAnywhere developer here, reposting what we just put on our forums. This turned out to be a fairly obscure problem on our hosting platform, and we've just pushed a system patch that fixes it.

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.

like image 162
Giles Thomas Avatar answered Sep 22 '22 08:09

Giles Thomas