Forums

Flask - Login issue when multiple users at the same time

I have built a small website with Flask, Flask-login and Flask-sqlalchemy with a classic user login.

When in production on pythonanywhere:

  • if a user A logs himself, he will see his data and views and everything is working ok.

  • Then, if a user B just connects to the website from another device at the same time, he will also see the session (and the data) of user A.

In local, I have no issue (it is difficult to have the same conditions as in production with another device but let say that I have no issue when using Incognito mode of my browser as the second user).

The code I am using:

init.py

# library
from flask import Flask
from flask_login import LoginManager
from flask_sqlalchemy import SQLAlchemy

# modules
from mywebsite_flask.config import config_selection


# init extensions
db = SQLAlchemy()
login_manager = LoginManager()

# app set-up
def create_app(config_mode):
    app = Flask(__name__)
    app.config.from_object(config_selection[config_mode])

    # flask-login init
    login_manager.login_view = "auth_bp.login"
    login_manager.init_app(app)

    # database init
    db.init_app(app)
    from mywebsite_flask.auth.models import Customer
    with app.app_context():
        db.create_all()

    # add blueprints
    from mywebsite_flask.public.routes import public_bp
    app.register_blueprint(public_bp)
    from mywebsite_flask.auth.routes import auth_bp
    app.register_blueprint(auth_bp)

    app.app_context().push()

    return app

models.py

# library
from flask_login import UserMixin

# modules
from mywebsite_flask import db, login_manager

class Customer(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)
    email = db.Column(db.String, unique=True)
    password = db.Column(db.String)
    token_verification = db.Column(db.Boolean, default=False)

    def __repr__(self):
        return f"Customer #{self.id}:{self.email}>"

@login_manager.user_loader
def load_user(customer_id):  # customer found by unique id
    return Customer.query.get(int(customer_id))

auth.routes.py

# library
from flask import Blueprint, flash, redirect, render_template, request, url_for
from flask_login import current_user, login_required, login_user, logout_user
from werkzeug.security import generate_password_hash

# modules
from mywebsite_flask import db
from mywebsite_flask.auth.models import Customer


# init
auth_bp = Blueprint("auth_bp", __name__)


@auth_bp.route("/login", methods=("GET", "POST"))
def login():
    if not current_user.is_authenticated:
        if request.method == "POST":
            email = request.form.get("email").lower()
            password = request.form.get("password")
            remember = True if request.form.get("remember") else False

            check_user = db.session.execute(db.select(Customer).filter_by(email=email)).scalar_one_or_none()

            if not various_check(check_user):
                # raise error if problem with user info
            else:
                login_user(check_user, remember=remember)
                return redirect(url_for("public_bp.home"))

        return render_template("auth/login.html")

    else:
        return redirect(url_for("core_bp.customer_home"))


@auth_bp.route("/logout", methods=("GET", "POST"))
@login_required
def logout():
    logout_user()
    return redirect(url_for("public_bp.home"))

# end

I am really struggling with that problem for several weeks. I have reviewed my code several times, looked at flask-login documentation and read some similar stackoverflow posts without being able to find a solution.

  • Can someone already have the issue on pythonanywhere ?
  • Could you see a problem with my code ?

Thanks a lot,

Michel

I couldn't load your web app, got 502 error -- could you check if it is currently operational? Also, could you shed some light what is auth_bp decorator doing? And where various_check function (used in definition of login) comes from? If I understand correctly the behavior you described looks like this: user A logs in, is redirected to public_bp.home, then user B hits /login endpoint and is automatically redirected to core_bp.customer_home -- is that correct? Could you add more logging to see exactly how the login request is being handled?

OK, I have found the problem.

In the app factory create_app() in init.py, I had app.app_context().push()

I have forgotten I added it as a shortcut some time ago. It was to easily access app.config parameters everywhere in the application.

The problem was solved by:

  • removing this app.app_context().push()
  • using current_app (if possible) or with app.app_context() (if not), in order to access app.config (my original need)

app.app_context().push() somehow interfered with the different sessions created on server (and more specifically on the current_user from flask login)

Glad to hear that you made it work!