Best way to have disappearing log-in page?

I’m creating a Dash App that requires me to have a user log-in before they can use the rest of the app (the layout for the rest of the app will involve a header, navbar, and content like input fields). The log-in page requires a username and password, and from there the username/password will be sent to a web API through a GET request in the ctor module. If the request is successful, it will return a token.

To have the log-in page that comes up at first, but then disappears when the users enters the username/password and gets a token, I made use of dcc.Store(type = ‘session’) so the log-in page wouldn’t come back when I refreshed the page (based off the Store clicks example here: Store | Dash for Python Documentation | Plotly). Is this the best way to do this?

Here’s a simplified version of what I did:

import dash
from dash import dcc, html, Input, Output, State, callback
import dash_bootstrap_components as dbc
from dash.exceptions import PreventUpdate
from pages import login_page, home_page, page1, page2
import ctor # my module 

# I'm using bootstrap.css saved locally in an assets folder
app = dash.Dash(__name__, suppress_callback_exceptions = True)
server = app.server

# Layouts ----------------------------------------------------------------------
# Header 
header = html.Div([
    html.H1('Header', style = {'textAlign': 'center', 'textDecoration' : 'underline'})
])

# Navbar
navbar = dbc.Nav([
    dbc.NavItem(dbc.NavLink('Input Page', href = '/', active = 'exact')),
    dbc.NavItem(dbc.NavLink('Analysis Page', href = '/page1', active = 'exact')),
    dbc.NavItem(dbc.NavLink('Extra Page', href = '/page2', active = 'exact'))
],
pills = True,
fill = True,
justified = True
)

# Layout for actual analysis
main_layout = html.Div([
    header,
    navbar,
    html.Div(id = 'page_content')

# Layout for log-in: Using dcc.input for username and password and html.Button for login button
login_layout = html.Div([
    login_page.login_layout
])

app.layout = html.Div([
    dcc.Location(id = 'url', refresh = False),
    dcc.Store(id = 'session', storage_type = 'session'),
    html.Div(login_layout, id = 'container')
)]

# Callbacks ----------------------------------------------------------------------

# Update the index when using main_layout
@app.callback(
    Output('page_content', 'children'),
    [Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/page1':
        return page1.page1_layout
    elif pathname == '/page2':
        return page2.page_layout
    else:
        return home_page.home_layout


# 1) Add a click to the session store
@app.callback(
    Output('session', 'data'),
    Input('button_login', 'n_clicks'), # from login_page.login_layout (html.Button)
    State('session', 'data'),
    State('input_username', 'value'), # from login_page.login_layout (dcc.Input)
    State('input_password', 'value') # from login_page.login_layout (dcc.Input)
)
def on_click(n_clicks, data, username, password):
    if n_clicks is None:
        # prevent the None callbacks is important with the store component.
        # you don't want to update the store for nothing.
        raise PreventUpdate

    # Give a default data dict with 0 clicks if there's no data.
    data = data or {'clicks': 0}
    user = ctor.User(username = username, password = password)
    # If the token was created (successful log-in), then we can consider the button clicked; otherwise not
    if user.token:
        data['username'] = username
        data['token'] = user.token
        data['clicks'] = data['clicks'] + 1
        del password
    return data

# 2) Output the stored click into the page
@app.callback(
    Output('container', 'children'),
    Input('session', 'modified_timestamp'),
    State('session', 'data'),
    State('container', 'children')
)
def on_data(ts, data, existing_content):
    if ts is None:
        raise PreventUpdate

    data = data or {}
    print(f'Data in on_data: {data}')
    if data.get('clicks', 0) > 0:
        return main_layout
    else:
        return existing_content


if __name__ == '__main__':
    app.run_server(debug=True)

Is dcc.Store(type = ‘session’) the best way to do this? It seems to work for so far.

Apologies if I missed something obvious; I’m still new to the dash module. Would love to hear someone else’s thoughts on this!