mkhorasani / Streamlit-Authenticator

A secure authentication module to validate user credentials in a Streamlit application.
Apache License 2.0
1.38k stars 229 forks source link

st.button calling authenticator.forgot_username returns None and empty tuple #30

Closed cmskzhan closed 1 year ago

cmskzhan commented 1 year ago

Still learning streamlit, so maybe a newbie question: Following your README example, I create the streamlit_local_auth.py As you can see from the code, I use a st.button to call forgot_username_button method.

def forgot_username_button(auth):
    try:
        username_forgot_username, email_forgot_username = auth.forgot_username('Find my username')

        if username_forgot_username:
            return st.success('Username sent securely')
            # Username to be transferred to user securely
        elif username_forgot_username == False:
            return st.error('Email not found')
        print(username_forgot_username, email_forgot_username)
    except Exception as e:
        return st.error(e)

if not authentication_status:
    if st.button("forgot username"):
        forgot_username_button(authenticator)

Unfortunately, it seems username_forgot_username, email_forgot_username returned from auth.forgot_username method are somehow None and ""(empty string). Even if I pass authenticator as a parameter!

Please help. Thx a lot!

mkhorasani commented 1 year ago

Hi @cmskzhan, try using the following an see if it works:

if not authentication_status:
    forgot_username_button(authenticator)
cmskzhan commented 1 year ago

@mkhorasani , yes that works, however, it would load the forgot username form immediately below login form. I'm trying to create a button of "forgot username" and the form only appears when you click on the button

mkhorasani commented 1 year ago

The problem with Streamlit widgets including buttons is that every time you interact with them, Streamlit will rerun the script thereby exiting any conditional if statement that a forgot username function is invoked in. A workaround would be to use your button as a toggle switch that saves a variable to session state that you will then use to invoke the forgot username function. Something similar to the below snippet:

if 'i_forgot_my_username' not in st.session_state:
    st.session_state['i_forgot_my_username'] = None

if st.button('I forgot my username'):
    if st.session_state['i_forgot_my_username'] == True:
        st.session_state['i_forgot_my_username'] = None
    else:
        st.session_state['i_forgot_my_username'] = True

if st.session_state['i_forgot_my_username']:
    forgot_username_button(authenticator)
nuass commented 1 year ago

good solution. @mkhorasani