Streamlit Session State - Deleted when switch tabs

I’m developing a dashboard and I need a login to reconcile with the user’s registration.

I followed these steps from Streamlit Docs:
Option 2: Individual password for each user

When using these steps I removed the part where it delete the st.session_state["username"], and then I realized that:

  • It ran before I put the username or password.
  • The layout was not so pretty.

So I changed it a bit and got the following code:

def check_password():
    """Returns `True` if the user had a correct password."""

    if "password_correct" not in st.session_state:
        st.session_state["password_correct"] = False
   
    if st.session_state["password_correct"] == False:
        col1, col2, col3 = st.columns([1.5,2,1.5])
        with col2:
             with st.form("Painel de Login"):
                  st.text_input("Username", key="username")
                  st.text_input("Password", type="password", key="password")
                  login = st.button("Login")
                  if login:
                       if (st.session_state["username"] in st.secrets["passwords"] and st.session_state["password"] == st.secrets["passwords"] [st.session_state["username"]]):
                              st.session_state["password_correct"] = True
                       else:
                              st.session_state["password_correct"] = False
                              st.error("😕 User not known or password incorrect")
    
    if st.session_state["password_correct"] == True:
        # Password correct.
        return True

The code ran fine, but it didn’t save the st.session_state[“username”] variable.

So I changed it and left it like this:

def check_password():
    """Returns `True` if the user had a correct password."""

    if "password_correct" not in st.session_state:
        st.session_state["password_correct"] = False
   
    if st.session_state["password_correct"] == False:
        col1, col2, col3 = st.columns([1.5,2,1.5])
        with col2:
             with st.form("Painel de Login"):
                  if ["username"] not in st.session_state:
                         st.session_state.username = st.text_input("Username")
                  if ["password"] not in st.session_state:
                         st.session_state.password = st.text_input("Password", type="password")
                  login = st.form_submit_button("Login")
                  if login:
                       if (st.session_state["username"] in st.secrets["passwords"] and st.session_state["password"] == st.secrets["passwords"][st.session_state["username"]]):
                              st.session_state["password_correct"] = True
                       else:
                              st.session_state["password_correct"] = False
                              st.error("😕 User not known or password incorrect")
    
    if st.session_state["password_correct"] == True:
        # Password correct.
        return True

That way, when the user logs into the dashboard, he saves the st.sessiont_state[“username”] but at first it keeps the login screen active, when I switch tabs it disappears.

After login:

After swithing tabs:

Some observations:

1.I already tried keeping the password_entered() function and making a callback on the st.form_submit_button
2.I already changed the if st.session_state["username"] == True to elif st.session_state["username"] == True or else.
3.I already changed the if st.session_state["username"] == False to if not st.session_state["username"]

In all these attempts, the result was that the problem of appearing the login box solved, but I needed to give 2 clicks on the Login button, and if the user made a mistake in the username, it did not correct the second time.

The only way that seems to work best is to declare the st.session_state["username"] using the key form and using the callback in st.form_submit_button:

def check_password():
    """Returns `True` if the user had a correct password."""
    def password_entered():
        """Checks whether a password entered by the user is correct."""
        if (
            st.session_state["username"] in st.secrets["passwords"]
            and st.session_state["password"]
            == st.secrets["passwords"][st.session_state["username"]]
        ):
            st.session_state["password_correct"] = True
        else:
            st.session_state["password_correct"] = False
            st.error("😕 User not known or password incorrect")

    if "password_correct" not in st.session_state:
        st.session_state["password_correct"] = False
   
    if st.session_state["password_correct"] == False:
        col1, col2, col3 = st.columns([1.5,2,1.5])
        with col2:
             with st.form("Painel de Login"):
                  st.text_input("Username", key="username")
                  st.text_input("Password", type="password", key="password")
                  login = st.form_submit_button("Login", on_click=password_entered)


    else:
        return True

But this way, when I switch tabs it deletes the st.session_state["username"].

After Login:

After Switch Tabs:

Hi @Guilherme_Hungaro -

This is expected, as the session is defined as within the browser. There have been a few Streamlit Components that have done some work with cookies / localstorage to try to provide a better cross-tab experience, but unfortunately I don’t have any personal experience with those components.

Best,
Randy

Nice!! Tks a lot Randy! This will definitely help!

1 Like

Hi @randyzwitch , I managed to find a solution!

What I did was basically use st.empty().
That way I got how to maintain.session_state which it kept! and maintain code performance maintain.

The code was written as follows:

var2 = st.empty()  
def check_password():
    """Returns `True` if the user had a correct password."""

    if "password_correct" not in st.session_state:
        st.session_state["password_correct"] = False

    if st.session_state["password_correct"] == False:   
      with var2:
        col1, col2, col3 = st.columns([1.5,2,1.5])
        with col2:
          with st.form("Login"):
            if ["username"] not in st.session_state:
              st.session_state.username = st.text_input("Username")
            if ["password"] not in st.session_state:
              st.session_state.password = st.text_input("Password", type="password")
            login = st.form_submit_button("Login")
            if login:
              if (st.session_state.username in st.secrets["passwords"] and st.session_state.password == st.secrets["passwords"][st.session_state.username]):
                st.session_state["password_correct"] = True
                return True
              else:
                st.session_state["password_correct"] = False
                st.error("😕 User not known or password incorrect")
                    
    elif st.session_state["password_correct"] == True:
        return True
         
if check_password():
     var2.empty()
1 Like