pythonauthenticationflaskauthorization

How to allow multiple accounts on the same browser in flask?


I'm following this tutorial: https://www.geeksforgeeks.org/how-to-add-authentication-to-your-app-with-flask-login/ but when I run the code, i open 2 tabs and i signup to test1 and test2 but then the first tab gets overwritten and both show test2, but i want to allow multiple accounts like discord or instagram if i have 2 tabs open i can have 2 accounts and if i close them or open a new one it just opens the latest account logged into


Solution

  • To log into different accounts in separate browser tabs, you need to avoid session sharing between tabs. By default, Flask uses cookies to store the session, which is shared across all tabs in the same browser. This is why when you log in on one tab, it overwrites the session in other tabs.

    Solution: Using Token-Based Authentication

    You can use JWT(Json Web Tokens) to manage authentication per tab. Each tab will have its own token, allowing different users to be logged in simultaneously.

    This is the example code snippet.

    from flask import Flask, request, jsonify, render_template, redirect, url_for
    from flask_sqlalchemy import SQLAlchemy
    from werkzeug.security import generate_password_hash, check_password_hash
    import jwt
    import datetime
    from functools import wraps
    
    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'your_secret_key'
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'
    
    db = SQLAlchemy(app)
    
    # User model
    class User(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        username = db.Column(db.String(50), unique=True)
        password = db.Column(db.String(80))
    
    # Utility to generate tokens
    def token_required(f):
        @wraps(f)
        def decorated(*args, **kwargs):
            token = request.cookies.get('token')
            if not token:
                return jsonify({'message': 'Token is missing!'}), 403
            try:
                data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=["HS256"])
                current_user = User.query.filter_by(username=data['username']).first()
            except:
                return jsonify({'message': 'Token is invalid!'}), 403
            return f(current_user, *args, **kwargs)
        return decorated
    
    @app.route('/signup', methods=['POST'])
    def signup():
        data = request.form
        hashed_password = generate_password_hash(data['password'], method='sha256')
        new_user = User(username=data['username'], password=hashed_password)
        db.session.add(new_user)
        db.session.commit()
        return jsonify({'message': 'Registered successfully!'})
    
    @app.route('/login', methods=['POST'])
    def login():
        data = request.form
        user = User.query.filter_by(username=data['username']).first()
    
        if not user or not check_password_hash(user.password, data['password']):
            return jsonify({'message': 'Login failed!'})
    
        token = jwt.encode({
            'username': user.username,
            'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=30)
        }, app.config['SECRET_KEY'])
    
        # Set token in cookies
        response = jsonify({'message': 'Login successful!'})
        response.set_cookie('token', token, httponly=True)
        return response
    
    @app.route('/logout', methods=['POST'])
    @token_required
    def logout(current_user):
        response = jsonify({'message': 'Logged out successfully!'})
        response.set_cookie('token', '', expires=0)
        return response
    
    @app.route('/profile')
    @token_required
    def profile(current_user):
        return jsonify({
            'username': current_user.username,
            'message': 'This is your profile'
        })
    
    if __name__ == '__main__':
        db.create_all()
        app.run(debug=True)
    

    You can find more tutorials and blogs to use JWT for authentication in Flask applications. I hope this will help you a little.