Black Lives Matter. Please consider donating to Black Girls Code today.

Flask-Login suport for dash

Uhm… I was trying to add Flask-Login support for my dash App but get some difficulties. After some study, I was able to make it work. The sample code below implement two end point app and the target is to add Flask-Login for both of them.

### testFlaskLogin.py
from flask import Flask
from flask import session
from flask_session import Session
from flask import Flask,render_template, flash,url_for,redirect,request,Response
from wtforms import Form, BooleanField, TextField, PasswordField, validators
from flask_login import LoginManager,login_user,logout_user,login_required
import sys,traceback
import datetime

server = Flask(__name__, static_url_path='',static_folder='static_files')

server.secret_key = 'j@i%^i@$tg$jij#$&*()^&'

class LoginForm(Form):
    username = TextField('Username', [validators.Length(min=4, max=25)])
    password = PasswordField('Password', [
        validators.Required(),
    ])

class User():
    username=None
    password=None
    defaultdb=None
    def __init__(self, username,  password=None, defaultdb=None):
        self.username = username
        self.password = password
        self.defaultdb = defaultdb
    def is_authenticated(self):
        return True
    def is_active(self):
        return True
    def is_anonymous(self):
        return False
    def get_credential(self):
        return self.username,self.password
    def get_defaultdb(self):
        return self.defaultdb
    def get_id(self):
        return self.username

@server.route("/logout")
@login_required
def logout():
    logout_user()
    return redirect('login')

@server.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm(request.form)
    if request.method == 'GET':
        return render_template('login.html', form=form)
    elif request.method == 'POST':
        if form.validate():
            # Login and validate the user.
            # user should be an instance of your `User` class
            username = form.username.data
            password = form.password.data

            user = User(username,password,default_db)
            login_user(user)
            flash('Logged in successfully.')
            next = request.args.get('next')
            return redirect(next or 'odorLiveUpdate')
        return render_template('login.html', form=form)

login_manager = LoginManager()
login_manager.login_view = "login"
login_manager.init_app(server)

@login_manager.user_loader
def load_user(user_id):
    return User(user_id)
###run.py
from testFlaskLogin import server as server
from app1 import app as app1
from app2 import app as app2

if __name__ == '__main__':
    server.run(debug=True,host='0.0.0.0',port=10090)
### app1.py
app = dash.Dash(name='app1', server=myserver, csrf_protect=False,url_base_pathname='/app1',loginSupported=True)
### app2.py
app = dash.Dash(name='app2', server=myserver, csrf_protect=False,url_base_pathname='/app2',loginSupported=True)

And the pull request: https://github.com/plotly/dash/pull/138

4 Likes

This doesn’t seem to work.

e.g. what’s the “myserver” below?

===================================

app1.py

app = dash.Dash(name=‘app1’, server=myserver, csrf_protect=False,url_base_pathname=’/app1’,loginSupported=True)

This definitely works.

The “myserver” is your flask hosting server (or app), e.g. myserver = Flask(name).
Besides, you need to pull the top request to overwrite the original dash py file to enable the flask-login.

An actual working example would probably help this post. Many, many people are looking for flask-login support for Dash.

yes, same here.
Just one more question? Does FlaskForm work with dash? I mean saving forms to/from the database? and then reading data for graphs?

Hello, you can see my example

2 Likes

Never too late for future travelers: @s1kor, I use wtf-forms to route my profile/settings pages from within flask, which are accessed by users in our sidebar, which we server from within our own Dash index.

@hypnotoad Hopefully the following will help the community.

To protect my routes I use inspiration directly from the Dash authentication library:

# setup needs
def create_app(blueprint=None):
    """
    The Flask application factory such that our sessions for each server
    application are modular and gardened. 
    """
    from spend.app import app as spend
    from execute.app import app as execute
    from presence.app import app as presence

    app = Flask(__name__)
    # instantiate configuration object from config.py
    app.config.from_object(Config)
    # generate random session key
    app.secret_key = os.urandom(16)
    # flask sqlalchemy extension
    db.init_app(app)
    # flask login extension
    login_manager.init_app(app)
    # redis db connection
    redis_client.init_app(app)
    # give our dash apps their servers
    execute.init_app(app)
    spend.init_app(app)
    presence.init_app(app)

    # from dash authentication repo
    for _app in [execute, spend, presence]:
        for view_name, view_method in _app.server.view_functions.items():
            _app.server.view_functions[view_name] = \
                login_required(view_method)
    return app

In each dash application file, i.e. execute, spend, presence above, I initialize the app with Dash(..., server=False) so that I can pass in my Flask app in the create_app factory.

Dash authentication repo