3

I've developed a web app that includes the functionality for users to log in and signup. I've done everything as per documentation and tutorials, and everything works fine with the flask server.

The issue is: I use gunicorn and start a web server, open the address (localhost:8000) on few different browsers (Brave and Firefox on Linux, and Brave on Android), I can only log in (Single or multiple different users) from only one client. When I try to do so from another one, it throws 400 Bad Request (CSRF Session token missing or CSRF Session tokens do no match).

Now, this doesn't happen when using Flasks Server. It only happens while using gunicorn.

I've deployed the application to Heroku (Using the Free plan), and I want multiple users to sign in at the same time. This happens on all of the other forms my app has.

All environment variables, secret keys are correctly configured, everything works as intended when using Flask Server. Using Gunicorn doesn't cause any other issues except this. Sometimes, logging in from a single client doesn't work too.

Any help would be appreciated. I've already looked at other threads/questions that were related, but they didn't mention the problem I have

Arsen Khachaturyan
  • 7,904
  • 4
  • 42
  • 42
  • Perhaps you could give more information how this is configured, some example that others can use to reproduce the problem? – VKolev Dec 17 '19 at 08:45

1 Answers1

3

Sorry for the late reply (Maybe it can help someone in the future)

The short answer :
use :

with app.app_context():
    your code

instead of :

app.app_context().push()

which is never closed

The long answer :

I guess you use Flask-WTF for managing CSRF, If yes, there is an if bloc (https://github.com/wtforms/flask-wtf/blob/0.15.x/src/flask_wtf/csrf.py#L53) in the generate_csrf function, which check the flask g variable before generating a new CSRF token. It works perfectly, but when the g variable doesn't reinitilize on each new request (see below for the cause) it creates a conflict between the different users trying to log in.

The principal cause of not reinitilizing the flask g variable is an app context which is pushed manually (usually by : app.app_context().push()) but not closed, in this case the app context is never torn down see : Flask app.teardown_appcontext not being called when DEBUG is false

Finally, i think there is something in the flask DEBUG mode, which force tearing down the app context and reinitilize the g variable.

elket
  • 31
  • 2
  • 1
    THANK YOU!!! After 2 full days of anguish, your solution did the trick for me. I had pushed my context. – JGV Aug 17 '22 at 14:19