mkhorasani / Streamlit-Authenticator

A secure authentication module to manage user access in a Streamlit application.
Other
1.63k stars 254 forks source link

Ability to Hide Sidebar on Login Page Until Authentication is Complete #192

Open shakkeel1330 opened 2 months ago

shakkeel1330 commented 2 months ago

Description:

I am using the streamlit-authenticator package in my Streamlit app, which has two pages: the main page and a secondary page. The sidebar displays both page options when the app loads, even before the user is authenticated.

To provide a better user experience, I want the sidebar to be hidden on the login page and only become visible after the user has successfully logged in.

I've tried using CSS to hide the sidebar initially, but I am unsure of the best way to integrate this with the streamlit-authenticator package. I would appreciate guidance on how to accomplish this.

Sample Code:

Below is an abstracted version of my current setup:

Main Page:

import streamlit as st
import streamlit_authenticator as stauth
import yaml
from yaml.loader import SafeLoader

st.set_page_config(initial_sidebar_state="collapsed")

def hide_sidebar():
    st.markdown(
        """
        <style>
        [data-testid="stSidebar"] {
            visibility: hidden;
        }
        </style>
        """,
        unsafe_allow_html=True
    )

def show_sidebar():
    st.markdown(
        """
        <style>
        [data-testid="stSidebar"] {
            visibility: visible;
        }
        </style>
        """,
        unsafe_allow_html=True
    )

with open('auth_config.yaml') as file:
    config = yaml.load(file, Loader=SafeLoader)

authenticator = stauth.Authenticate(
    Hasher.hash_passwords(config['credentials']),
    config['cookie']['name'],
    config['cookie']['key'],
    config['cookie']['expiry_days'],
    config['pre-authorized']
)

authenticator.login()

if st.session_state['authentication_status']:
    show_sidebar()
    authenticator.logout(location='sidebar', key='main_logout')
    # Main page content
else:
    hide_sidebar()
    if st.session_state['authentication_status'] is False:
        st.error('Username/password is incorrect')
    elif st.session_state['authentication_status'] is None:
        st.warning('Please enter your username and password')

Second page:

import streamlit as st
import streamlit_authenticator as stauth
import yaml
from yaml.loader import SafeLoader

def show_sidebar():
    st.markdown(
        """
        <style>
        [data-testid="stSidebar"] {
            visibility: visible;
        }
        </style>
        """,
        unsafe_allow_html=True
    )

with open('auth_config.yaml') as file:
    config = yaml.load(file, Loader=SafeLoader)

authenticator = stauth.Authenticate(
    Hasher.hash_passwords(config['credentials']),
    config['cookie']['name'],
    config['cookie']['key'],
    config['cookie']['expiry_days'],
    config['pre-authorized']
)

authenticator.login()

if st.session_state['authentication_status']:
    show_sidebar()
    authenticator.logout(location='sidebar', key='secondary_logout')
    # Secondary page content
else:
    hide_sidebar()
    if st.session_state['authentication_status'] is False:
        st.error('Username/password is incorrect')
    elif st.session_state['authentication_status'] is None:
        st.warning('Please enter your username and password')

Directory structure:

├───src │ ├───pages │ │ └───second_page.py │ ├───services │ ├───utils │ ├───main.py ├──────

Expected Outcome:

  1. The sidebar should be hidden on the login page.
  2. After successful login, the sidebar should be displayed with the available pages.

Any assistance on how to achieve this would be greatly appreciated!

Screenshot 2024-08-09 223314

shakkeel1330 commented 2 months ago

Hi @mkhorasani, Thank you for developing this great package! I just wanted to quickly check again if you have any suggestions with handling the issue I mentioned above.

mkhorasani commented 2 months ago

Hi @mkhorasani, Thank you for developing this great package! I just wanted to quickly check again if you have any suggestions with handling the issue I mentioned above.

Hi @shakkeel1330, thank you for reaching out. Unfortunately, not yet, I'm currently inundated with a relatively large backlog of items to address. Will try my best to attend to this at some point in the near future too!

ThomasRohde commented 1 month ago

This works for me:

import streamlit as st
import streamlit_authenticator as stauth
import yaml
from yaml.loader import SafeLoader
from streamlit_authenticator.utilities import (Hasher, LoginError)

with open('./config.yaml') as file:
    config = yaml.load(file, Loader=SafeLoader)

Hasher.hash_passwords(config['credentials'])

authenticator = stauth.Authenticate(config['credentials'],
                                    config['cookie']['name'],
                                    config['cookie']['key'],
                                    config['cookie']['expiry_days'],
                                    config['pre-authorized'])

def login():
    pass

try:
    authenticator.login()

except LoginError as e:
    st.error(e)

if st.session_state['authentication_status']:
    with st.sidebar:
        authenticator.logout()

    # Define pages
    pages = [
            st.Page("apps/page1.py", title="Page1"),
            st.Page("apps/page2.py", title="Page2"),
        ]

    # Use st.navigation
    page = st.navigation(pages)

    # Run the selected page
    page.run()

elif st.session_state['authentication_status'] is False:
    st.error('Username/password is incorrect')
elif st.session_state['authentication_status'] is None:
    st.navigation([st.Page(login, title="Login")])