Playing with multiple ways of authenticating through a Google account within Streamlit:
- Decomposing server-side OAuth flow through Google Auth Oauthlib and FastAPI to catch redirect URIs and manage session cookies
- Google Signin Button in a Streamlit Component
- Firebase Authentication with Firebase UI in a Streamlit Component
- A Google Project. Initialize one from the GCP Console
- A Firebase Project. To keep things tidy, create a Firebase project over the previously created GCP Project through the Firebase Console
- For practice's sake, enable local HTTPS for your Streamlit app
- I ran
openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365in WSL2 on Windows. - Then moved
cert.pemandkey.pemto.streamlitfolder at root of project - Finally added
sslCertFile = ".streamlit/cert.pem"andsslKeyFile = ".streamlit/key.pem"to.streamlit/config.toml
- I ran
[server]
sslCertFile = ".streamlit/cert.pem"
sslKeyFile = ".streamlit/key.pem"Better use Caddy or Nginx to SSL proxify Streamlit & FastAPI
Head to GCP Console
-
In APIs and services > OAuth consent screen:
- configure email, links on first page.
- in Scopes second page, add OpenID Connect scopes:
openid,../auth/userinfo.profileand.../auth/userinfo.email.- If you enabled the
Calendar API(either by typing it in search bar or from APIs and services >Enabled APIs and Services), add the.../auth/calendar.events.readonlyto ask the user for Calendar authorization
- If you enabled the
-
add tests users in 3rd page
-
In APIs and services > Credentials, create a OAuth 2.0 Web Client ID and download it as a JSON file
client_secret.jsonto the root of the project.- As authorised Javascript origins, I added the local Streamlit URL:
https://localhost:8501 - As authorised redirect URIs, I added:
http://localhost:9000/: Flask endpoint from google-oauthlib'sInstalledAppFlow.run_local_serverandget_user_credentialsmethodshttp://localhost:8000/auth/codeandhttp://localhost:8000/auth/token: our own FastAPI callback endpoints
- As authorised Javascript origins, I added the local Streamlit URL:
- Copy the credentials
client_idandclient_secretto.streamlit/secrets.tomlfile
client_id="XXX.apps.googleusercontent.com"
client_secret="XXXXXX-..."Next, head to Firebase Console
- In Firebase Authentication > Sign-in method, enable Google Provider.
- In Project Overview > Project Settings > Service Acctouns, generate a new private key and download JSON file as
firebase_secret.jsonto the root of the project. - In Project Overview, click the
Add appbutton, and add aWebApp. After creation, copy thefirebaseConfigvariable into afirebase_client.jsonfile at the root of the project.
Install Python packages: pip install -r requirements.txt
Run Streamlit multipage app: streamlit run streamlit_app.py
- Access Streamlit app in
https://localhost:8501
For pages 3 and 4, run FastAPI redirect server in parallel: fastapi dev fastapi_server.py.
- Access FastAPI OpenAPI in
http://localhost:8000/docs. Visualize state of app in/sessionsURI.
- Good enough for local / on-premise deployments
- Wouldn't work on Streamlit Cloud because the Flask port is not open. Create your own Docker image to expose Streamlit + Flask ports
- Deploy FastAPI separately as authentication and session cookie management service
- Hide both services behind reverse proxy with single URL
- I think it's a difficult setup to maintain. FastAPI + DB session cookies to replace with Firebase Authentication or Auth0 if you don't have time for this like me...
- When Native OAuth+OIDC, redirects and custom endpoints appear in Streamlit, this solution seems the best
- Streamlit Component which embeds Google / Firebase signin
- Google signin stores SIDCC cookie, Firebase uses API Keys+JWT in IndexedDB on browser to track user session
- Because of Streamlit Component iframe embed, doesn't work in deployments because CSRF issues. Streamlit host and iframe embedding signin have different addresses.
- Google Tap has intermediate Iframe that may solve this?



