Home > database >  Flask - login impacts multiple sessions
Flask - login impacts multiple sessions

Time:10-13

I recently deployed my first flask project to pythonanywhere and am experiencing a bug that did not appear on my development server with flask-login. Whenever I log in on one device, all devices that navigate to the webpage appear to be logged in as that user.

I am also experiencing CSRF Token errors which I believe may be related. Sometimes I am seeing "The CSRF tokens do not match" and other times "The CSRF session token is missing"

I spent 4 hours searching for where this could be originating from, but i'm not seeing anything in the documentation regarding this type of error. Has anyone ever experienced anything similar and have any thoughts as to where I should be looking?

__init__.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_login import LoginManager
from flask_migrate import Migrate
from flask_mail import Mail
from flask_wtf.csrf import CSRFProtect
import os

app = Flask(__name__)
csrf = CSRFProtect(app)

app.config['SECRET_KEY'] = os.getenv('SECRET_KEY')
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
login_manager = LoginManager(app)
login_manager.login_view = 'users.login'
login_manager.login_message_category = 'info'
app.config['MAIL_SERVER'] = 'smtp.gmail.com'
app.config['SERVER_NAME'] = '*REDACTED*'
app.config['SESSION_COOKIE_DOMAIN'] = False
app.config['SESSION_COOKIE_SECURE'] = False
app.ssl_context='adhoc'
app.app_context().push()

from flask import g, session
from app import app

from flaskpm.users.routes import users
from flaskpm import models

migrate = Migrate(app, db, render_as_batch=True)

app.register_blueprint(users)

routes.py

from flask import render_template, url_for, flash, redirect, request, Blueprint, g, session
from flaskpm import app, db, bcrypt, mail, login_manager
from flaskpm.users.forms import LoginForm, RegistrationForm, RequestResetForm, ResetPasswordForm
from flaskpm.models import User
from flask_login import login_user, current_user, logout_user, login_required
from flask_mail import Message
from secrets import token_hex

users = Blueprint('users', __name__)

@login_manager.user_loader
def load_user(user_id):
    return User.get(user_id)

@users.route("/login", methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('properties.home'))
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(email=form.email.data).first()
        if user and bcrypt.check_password_hash(user.password, form.password.data):
            login_user(user, remember=form.remember.data)
            next_page = request.args.get('next')
            if user.active:
                return redirect(next_page) if next_page else redirect(url_for('properties.get_properties'))
            else:
                flash('Login Unsuccessful. User account has not been activated by the administrator', 'danger')
        else:
            flash('Login Unsuccessful. Please check email and password', 'danger')
    return render_template('login.html', title='Login', form=form)

login.html

{% extends "layout.html" %}
{% block content %}
<main role="main" >
  <div >
      <div >
        <div >
          <form method="POST" action="">
            <fieldset >
              {{ form.hidden_tag() }}
              <legend >Log In</legend>
              <div >
              {{ form.email.label() }}
              {% if form.email.errors %}
                {{ form.email() }}
                <div >
                  {% for error in form.email.errors %}
                    <span>{{ error }}</span>
                  {% endfor %}
                </div>
              {% else %}
                {{ form.email() }}
              {% endif %}
              </div>
              <div >
                {{ form.password.label() }}
                {% if form.password.errors %}
                  {{ form.password() }}
                  <div >
                    {% for error in form.password.errors %}
                      <span>{{ error }}</span>
                    {% endfor %}
                  </div>
                {% else %}
                  {{ form.password() }}
                {% endif %}
              </div>
              <div >
                {{ form.remember() }}
                {{ form.remember.label() }}
              </div>
            </fieldset>
            <div >
                {{ form.submit() }}
            </div>
            <small >
              <a href="{{ url_for('users.reset_request')}}">Forgot Password?</a>
            </small>
          </form>
        </div>
{% endblock content %}

CodePudding user response:

I suspect that a large part of your issue may be that in __init__.py you first create app with

app = Flask(__name__)

and then, a few lines later, you overwrite it with

from app import app

You'll need to rename one of those and, in the code, decide which of them each of the actions needs to be applied to.

  • Related