Search code examples
reactjsflask

Flask-Login : Logout_user does not clear session or logout user properly


Hey so I asked a question recently that was about how my login user wasnt prsisting the login user accross cors requests and routes but then i fixed it with this app.config.update(SESSION_COOKIE_SAMESITE="None", SESSION_COOKIE_SECURE=True) and by adding {with : credentials} to my frontend requests. Though after fixing how my logged in user always stays logged in I noticed that logout_user() doesnt work no matter what I do. I clear the session, I log out the user, and i even tried to delete the cookie itself in the code. Only way to log out is to go on edge and delete it in the settings. Though I have no idea why it wouldnt work please help. Ive debugged it properly and it wont log out. It actually only logs out on routes that i specify like the debug route which does log out but not anywhere else just on that specific route. Heres my full backend code:

from flask import Flask, jsonify, request, session,make_response
from flask_cors import CORS
from flask_login import LoginManager, UserMixin, login_user, logout_user, current_user
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
import sqlalchemy.orm as so
from sqlalchemy.orm import Mapped, mapped_column
import sqlalchemy as sa
from dotenv import load_dotenv
from werkzeug.security import generate_password_hash, check_password_hash
import os

# Load environment variables
load_dotenv()

app = Flask(__name__)
# Use DATABASE_URL from the environment, fallback to local development URI
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv(
    'DATABASE_URL', 'sqlite:///users.db')

app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'default_secret_key')
app.config.update(SESSION_COOKIE_SAMESITE="None", SESSION_COOKIE_SECURE=True)

CORS(app, supports_credentials=True)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
login_manager = LoginManager(app)

@login_manager.user_loader
def load_user(id):
    return User.query.get(int(id))
class User(UserMixin, db.Model):
    __tablename__ = "user"
    id : Mapped[int] = so.mapped_column(primary_key=True)
    username : Mapped[str] = so.mapped_column(unique=True)
    password_hash : Mapped[str] = so.mapped_column()
    def __repr__(self):
        return f"{self.id}/{self.username}/{self.password_hash}"
@app.route("/debug_session")
def debug_session():
    logout_user() 
    session.clear()
    return jsonify(current_user.username)
@app.route("/userreg", methods=["POST"])
def registry():
    data = request.get_json()
    
    if User.query.filter_by(username = data["username"]).first() != None:
        return ("Taken")
    else:
        password = generate_password_hash(data["password"])
        db.session.add(User(username=data["username"], password_hash=password))
        db.session.commit()
        return ("Registered")
@app.route("/logout", methods=["POST"])
def logout():
    # Logout user
    logout_user() 
    session.clear()
    return jsonify("bro!")
@app.route("/userlog", methods=["POST"])
def login():
    data = request.get_json()
    user = User.query.filter_by(username=data["username"]).first()
    if user is None:
        return {"success": "No", "message": "User not found"}, 404
    checkpassword = check_password_hash(user.password_hash, data["password"] )
    if checkpassword:
        login_user(user)
        return {"success" : "Yes"}
    else:
        return {"success" : "No"}
@app.route("/currentuser", methods=["GET", "POST"])
def currentuser():
    
    if current_user.is_authenticated:
        return {"username" : current_user.username, "authenticated" : True}
    else:
        return {"username" : "NotLogged", "authenticated" : False}
@app.route("/")
def start():
    return jsonify(current_user.username)

Heres what my frontend post for logout looks like tho its probably a problem with the backend:

async function Logout() {
    
    await axios.post("http://127.0.0.1:5000/logout", { withCredentials: true })
    .then(() => {
        setuserdata(null)
    })

I tried almost everything I said above. deleteing the cookie itself on vscode etc.


Solution

  • The command axios.post(url[, data[, config]]) has several optional attributes. You are sending the config as data because you assigned the attributes incorrectly. The following code should work.

    await axios
        .post("http://127.0.0.1:5000/logout", null, { withCredentials: true })
        .then(() => {
            setuserdata(null);
        });