Multi page app - hide pages based on user

I understand that in Streamlit’s multipage app structure, each file in the pages folder is automatically rendered as a separate page in the application’s sidebar. I’m trying to create a Streamlit app where, upon visiting, only a “Sign In” page is initially visible in the sidebar. After a successful sign-in, the app should display the other pages in the sidebar and hide the “Sign In” page.

To achieve this, I need to dynamically show or hide pages in the sidebar based on certain conditions—in this case, whether the user is part of a specified list of users. If the user is on the list, I want to display all pages; otherwise, I only want to display a single page. However, it appears that all files in the pages folder are rendered by default, with no straightforward way to control which pages are displayed based on these conditions.

Use st.Page and st.navigationto change what pages are available to a user: Define multipage apps with st.Page and st.navigation - Streamlit Docs

Hi @SiddhantSadangi, thank you for your response!

I’m using OAuth2Session for authentication and then added the following code:

# List of admin names
ADMIN_NAMES = ["Name"] 

# Function to show the dashboard based on role
def show_page():
    if st.session_state.role == "User":
        st.title("User Page")
        # Display user-specific pages
        user_page = st.Page("user/1_user.py", title="User Page")
        account_page = st.Page(logout, title="Log out")
        st.navigation([account_page, user_page])

    elif st.session_state.role == "Admin":
        st.title("Admin Page")
        # Display both admin and user pages for admins
        user_page = st.Page("user/1_user.py", title="User Page")
        admin_page_1 = st.Page("admin/2_admin.py", title="Admin Page 1")
        account_page = st.Page(logout, title="Log out")
        st.navigation([account_page, user_page, admin_page_1])

# Check if the user is already authenticated and their role
def main():
    if "oauth_token" in st.session_state:
        user_name = st.session_state.user_info['name']  # Get the user's name
        st.write(f"Hello, {user_name}!")
        
        # Check if the user is an admin
        if user_name in ADMIN_NAMES:
            st.session_state.role = "Admin"
        else:
            st.session_state.role = "User"

        # Show the appropriate content based on the user's role
        show_page()

    else:
        if 'oauth_token' not in st.session_state and 'code' in st.query_params:
            handle_oauth_callback()  # Handle the OAuth callback and retrieve user info
        else:
            st.write("You are not logged in. Please log in to continue.")
            redirect_to_login(False)  # Redirect to login page

if __name__ == "__main__":
    main()

However, it’s not functioning as expected. After logging in, the sidebar doesn’t appear. I’m new to using Streamlit and would really appreciate your help with this. Thanks in advance!

Hi,

st.navigation returns the current page which can be executed by .run() method, you need to incorporate .run() method in your code.

pg = st.navigation([st.Page("page_1.py"), st.Page(page_2)])
pg.run()

The only reason I see for the sidebar not being displayed is the oauth_token not being in session state, or st.session_state.role not in ["User", "Admin"].

After logging in, can you write the contents of st.session_state to check if the oauth_token and roles are as expected?

You can also simplify show_page() to as follows:

def show_page():
    user_page = st.Page("user/1_user.py", title="User Page")
    account_page = st.Page(logout, title="Log out")
    admin_page_1 = st.Page("admin/2_admin.py", title="Admin Page 1")
    
    if st.session_state.role == "User":
        st.title("User Page")
        # Display user-specific pages
        st.navigation([account_page, user_page])

    elif st.session_state.role == "Admin":
        st.title("Admin Page")
        # Display both admin and user pages for admins
        st.navigation([account_page, user_page, admin_page_1])

Since account and user pages will be shown irrespective of the role, try moving them outside the if-else block to see if the sidebar is now being rendered