I am having issues trying to find a solution for keeping the authentication of a user using plotly dash with flask and gunicorn. It seems that if another user queries the server or even after a while of jumping from one dashboard to the other, the session user information gets lost.
# app.py
import dash
import dash_bootstrap_components as dbc
from dash import html, dcc, Input, Output, State
from flask import Flask, session
from flask_session import Session
from redis import Redis
from datetime import timedelta
import os
import secrets
# Initialize the Flask server
server = Flask(__name__)
server.secret_key = os.environ.get('SECRET_KEY', secrets.token_urlsafe(16))
# Configure Flask-Session with Redis
server.config["SESSION_TYPE"] = "redis"
server.config["SESSION_PERMANENT"] = True
server.config["SESSION_USE_SIGNER"] = True
server.config["PERMANENT_SESSION_LIFETIME"] = timedelta(minutes=30)
server.config["SESSION_REDIS"] = Redis(host='localhost', port=6379) # Adjust Redis host/port if needed
# Initialize Flask-Session
Session(server)
# Initialize the Dash app
app = dash.Dash(__name__, server=server, external_stylesheets=[dbc.themes.BOOTSTRAP], suppress_callback_exceptions=True)
# Layout for login modal and navbar
app.layout = html.Div([
dcc.Location(id='url', refresh=True),
html.Div(id='page-content'),
dbc.Modal(
[
dbc.ModalHeader("Login"),
dbc.ModalBody([
dbc.Input(id='username', type='text', placeholder='Username'),
dbc.Input(id='password', type='password', placeholder='Password'),
dbc.Button('Login', id='login-button', color="primary")
]),
], id="login-modal", is_open=True
),
dbc.NavbarSimple(
children=[
dbc.Button("Logout", id="logout-button", color="danger", className="ml-auto")
], brand="App", color="dark", dark=True, id='navbar', style={'display': 'none'}
),
])
# Simulated user database
USER_DATABASE = {
'test_user': 'test_password',
'test_user2': 'test_password'
}
@app.server.before_request
def refresh_session():
session.modified = True # Refresh session TTL on each request
# Callback to handle login and logout
@app.callback(
[Output('login-modal', 'is_open'), Output('navbar', 'style')],
[Input('login-button', 'n_clicks'), Input('logout-button', 'n_clicks')],
[State('username', 'value'), State('password', 'value')],
prevent_initial_call=True
)
def handle_login_logout(n_login, n_logout, username, password):
# Login process
if n_login and username in USER_DATABASE and USER_DATABASE[username] == password:
session['user'] = {'username': username} # Store user session
return False, {'display': 'block'} # Close login modal, show navbar
# Logout process
if n_logout:
session.pop('user', None) # Clear session
return True, {'display': 'none'} # Reopen login modal, hide navbar
return dash.no_update, dash.no_update
# Redirect logic
@app.callback(
Output('page-content', 'children'),
[Input('url', 'pathname')]
)
def display_page(pathname):
if 'user' in session:
return html.Div([html.H1(f"Welcome, {session['user']['username']}"), html.P("This is your dashboard.")])
return html.Div([html.H1("Please log in to access this page.")])
if __name__ == '__main__':
app.run_server(debug=True)
The following is a dashboard under āpagesā directory:
$ home.py
import dash
import dash_bootstrap_components as dbc
from dash import html, dcc
from flask import session
import dash
dash.register_page(__name__)
def layout():
# Check if user data is available in the session
user = session.get('user')
if not user:
# Redirect to a login page or show a message if no user is found in session
return html.Div("Please log in to access this page.")
# Display the user's info pulled from the session
return dbc.Container(fluid=True, children=[
dbc.Row([
dbc.Col([
html.H2(f"Welcome, {user['username']}!"),
html.P("This is your personal dashboard."),
html.P(f"Email: {user['email']}"),
dbc.Button("Logout", id="logout-button", color="danger", className="mt-3")
], width=6)
], justify="center")
])
Can someone please tell me how I can retain an individual users session information in order for me to ensure the user is authenticated and that I can pull user tailored data from a database, if I wanted to? The issue that I keep seeing is that the session stored data keeps being deleted if another user is querying anything from the server.