We are investigating approaches to add native authentication support for Streamlit, as it is one of the top most requested community features. This is a rough proposal for how it might work, which is shared for your feedback.
This is cross-posted in Github issue #8518
Goals
Goal 1: Provide the building blocks for integrating more robust auth solutions including:
- documented support for reading headers (replace the undocumented but heavily used
_get_websocket_headers()
- native support for reading and writing cookies ( #861 )
- native redirect ( #7123 )
- hooks to add identity information in
st.user
- [longer term] Support custom http endpoints ( #439 ) - this will be a bigger effort but know we probably need to get there eventually to have a really robust support
- ??? What else ???
Goal 2: Provide an out-of-the-box native integration which covers the most common use cases, especially for developers getting started. To that end, we propose standardizing on OAuth2 & OpenID Connect as the natively supported protocols in Streamlit.
- This would be an opinionated and minimal implementation, geared towards integrating with standardized OIDC providers.
- Goal would be, with a few lines of config / secrets, you can be set up with
login()
/logout()
methods and the users verified email, OAuth2 token, and potentially other claims from a JWT readily available through a standard API (likely attributes onst.user
). - Ideally, include an easy integration with cookies support so it’s trivial to maintain the user auth session across tabs for some time. However, we still need to investigate whether this is feasible or has other major implications.
Why OpenID Connect (OIDC)?
- From our perspective, OIDC seems like the most modern, standardized authentication protocol we can use which enables a standard format of user identity claims (including roles / groups) and minimal custom code across providers.
- We also see a wide range of adoption across identity providers both in the consumer space (Google, Apple, etc) and enterprise space (Auth0, AWS Cognito, MSFT Entra ID, etc).
- For most app developers who aren’t working in a more sophisticated existing platform, it seems to cover the typical use case for “single sign on” for relatively low fuss and configuration required in the provider side.
Non-goal: Replace the use of reverse proxy in higher security environments
We know this practice of running Streamlit behind an auth proxy and forwarding authenticated requests to the app is fairly common among Streamlit usage in bigger companies or those with higher security requirements. We want to build library features that make that easier to run (such as documented headers support) but not replace it or build extremely hardened security into Streamlit, since it isn’t our expertise.
But, we think this proposal can still unblock many developers operating in somewhat lower stakes environments who experience a lot of friction today.
VERY ROUGH API sketch
Here’s a very rough first idea of how the API might work for the built-in OIDC.
# .streamlit/secrets.toml or similar
[auth] # reserved group for defining auth, could also support multiple like [auth.google]
type = "oidc"
provider = "google" # or api_base_url="accounts.google.com"
client_id = "SOME ID"
client_secret = "SOME SECRET"
default_ttl = "7d" # if we have some easy cookie support
Once this is configured, you can call some standard methods in the app which will redirect to the appropriate OIDC flow. Streamlit will automatically expose an OAuth2 callback endpoint which handles the response from the identity provider.
In the case below, calling login()
will simply redirect to the OAuth2 flow. When the user returns from the flow, their identity values will be available in st.user
. Calling logout()
will clear the values from st.user
in that session along with any browser cookies.
# streamlit_app.py
if st.user.logged_in(): # verify log in, including cookie from an earlier session
st.write(f"Welcome, {st.user.name}!")
st.sidebar.button("Logout", on_click=st.user.logout)
else:
st.sidebar.button("Login", on_click=st.user.login)
Other authentication protocols
We know other protocols are used today, such as looking up a username / password in a database (e.g. Streamlit-Authenticator), or more complex delegated authentication schemes like SAML / LDAP. In some cases, the existing plugins / components for these can work pretty well. We’d like to provide some hooks to make them more consistent with the native support (maybe similar to st.connection
), but it may not be in the initial launch.
What do you think?
If this proposal and approach sounds good and meets your use case, please give a . Also, we’d love to hear any comments about what you like, don’t like, or would change, or any use case you have which would not be supported. Thanks!!