A "multi page" app with authentication, verification and session state

Hi everyone,

I’ve been roaming around the Streamlit community for a while now but just felt like sharing a little half-done side project I’ve been building with Streamlit.
It’s a multi page app using session state, which uses a firebase integration for all account management/mail verification and a local mongodb to store some arbitrary things like the data for the “house reference table”.

Feel free to ask me questions about it :slight_smile: It was a bit of a learning experience getting the cached firebase integration working and not making new connections over and over again and to set up the session state correctly for navigation but I made it work!

Check out the app demo over here:

Have an awesome week :fire:

11 Likes

Thanks bro :pray: :raised_hands: :blue_heart:

1 Like

github link?

1 Like

Wow, is your app auto-translated according to the visitor’s location?

1 Like

Glad people like it! :sunglasses:

I’m currently working on it in a private Gitlab repo since I’m using it for one of my own apps but I’ll look into making a public Github repo for it so everyone can use it as a starting point for a Streamlit webapp. Just have to make it a little bit more accessible with some docs explaining how to set it up.

I’ll post back here once I made it public so check back in a while :slight_smile: I’m a bit swamped at work at the moment but shouldn’t take ages.

@xzrokeman not yet but I actually looked into that and tried multiple packages to implement that functionality. Might add that in a future release. Still have some features to complete and some bugs to squash(the forgot password button sometimes loads slower than the other ones and it fails to be “pressable” at some runs, it’s a tough bug to reproduce but I’ll figure it out before I make the project public!)

@WhySecond Thanks as well bro! <3

Have an awesome day everyone :partying_face:

I think the translation is done by your browser.

1 Like

Hey @Fhireman ! I’m currently making an organization internal web app and need the same thing that you make, but I’m using hydralit component to make a nav bar for my app. As from the video you uploaded, it seems that you use firebase as your authenticator, and I do to. Are you using the python admin sdk for firebase or are you using Pyrebase? Because I’m having trouble to make the verify email thingy as I don’t know how the bits and bob work, the logging in without verifying works well though, but an extra verification step don’t hurt, hope you can help a bit with that, thanks!

1 Like

Hi there!
Sounds awesome, I was actually looking into Hydralit as well but wanted to make this as close to vanilla Streamlit as possible. I really hope the Streamlit team adds an optional navbar like that though! Would make it less of a hassle to make multiple “pages”.

I indeed use Pyrebase (pyrebase4) for the Firebase integration, I’ll come back to you on that with some examples of how I did it :slight_smile: It’s pretty easy to set up but the documentation on it is lacking a bit(like what kind of errors to expect from the Firebase API side).

I’ll try to reply with some info tonight!

Hi again,

Alright so most of the steps are actually on the Github page of Pyrebase but this is the one I’m using:

Seeing as you already have the login working I’m assuming that you know how to setup the Firebase project, register account and e-mail login, please let me know if you need help with that too :slight_smile:

In my logic for the on_submit of the register account form I have a check that if the account registration was successful, I immediately follow-up with the verification mail method.
I pass the email and password of the newly registered account along to the verification mail method cause we need it for the login method since we need the result it returns to send the verification mail.

So the end result looks a little something like this(where auth holds a reference to the firebase authentication object):

def page_create_account(self, auth):
    st.markdown("### $1000000000 for an account pls :money_with_wings:")
    with st.form(key='register_form'):
        email = st.text_input("Just kidding we only need your email for this test :D")
        password = st.text_input("Password", type="password")
        confirm_password = st.text_input("Confirm password", type="password")
        submit_button = st.form_submit_button(label="Submit")

     if submit_button:
        # Put your own checks for empty/wrongly filled register account form fields here
        if auth.create_user_with_email_and_password(email, password):
            # Put your own checks for a successful registered account here
            result = auth.sign_in_with_email_and_password(email, password)
            # The line below actually sends the verification mail
            auth.send_email_verification(result["idToken"])
            st.success("kaching! account created :eyes:, please verify your e-mail address with the link that we've mailed you!")
        

As you can see we get a user object/result from the sign_in method, this contains the idToken that we send along with the send_email_verification method so we can send out the mail.

To get more info about the verification status of the e-mail you can use a check like below:

user_obj = auth.get_account_info(result["idToken"])
email_verified = user_obj["users"][0]["emailVerified"]
if email_verified:
    return True
else:
    st.error("Please verify your e-mail address.")
    return False

It’s a bit simplified since I’ve abstracted away most of my auth methods in its own auth.py script but I hope it helps you implement the verification mails!

Let me know if it works or not :smiley:

Thank you so much! I didn’t know that you can get the emailVerified parameter from the accountinfo call, thanks a lot, I’ll follow up if it works, thanks again!

1 Like

@Fhireman
Hi, have you try to capture cookie to do the identity check?

Hey man, I’m wondering if you have made a demo with a repo for the login.

ENJOY

1 Like

@Fhireman Hi, sorry to bump this thread. I am trying to make exactly the same application as yours, but I am stuck.

I am using mongodb instead of firebase and am able to successfully login and register, but the problem which I am facing is that unauthorised users, i.e., those who have not successfully logged in are able to view the pages.

@Fhireman Would you kindly mind providing the source code for this? It looks like something that perfectly captures my current needs. I’ve never worked with Firebase before.

1 Like

Hey everyone,

Apologies that I didn’t get around to posting a Firebase auth blueprint project yet, didn’t expect people to ask for it so much.
I’ll dive into my old projects coming Sunday and if I find it I’ll make a GitHub project you can all clone and get it up and running without a hassle with just your Firebase key.

Don’t hesitate to remind me if I happen to not reply here!

1 Like

image

Good news everyone, I found the project in my disorganized warehouse of projects :slight_smile:

Will clean it up and get it ready to go on GitHub coming Sunday :+1:

1 Like

Great job! Your effort is truly appreciated.

I wanted to share with you a recreation I made, which is refactored from the ‘streamlit_authenticator’ package. I implemented a solution that leverages JSON Web Token (JWT) cookies to maintain the user’s login state across browser sessions. For the backend, I used Google’s Firebase Admin Python SDK. This solution ensures that the content of the page and user settings panel are only displayed if the user is authenticated. Similarly, the login page can only be accessed if the user is not authenticated. Upon registration, the user is sent a verification link to their e-mail address.

Important - to make this app run, put the following variables in your secrets.toml file:

  • COOKIE_KEY - a random string key for your passwordless reauthentication
  • FIREBASE_API_KEY - Key for your Firebase API (how to find it)
  • firebase_auth_token - Information extracted from Firebase login token JSON (how to get one).

To give you a better idea of what I created, I’ve attached some screenshots below. I hope people here will find it helpful!



1 Like

Thanks!
With your JWT implementation it actually seems like a better solution than mine probably. But I’ll share my project anyways :slight_smile:

1 Like