Best practice for secure, per-user authentication/session management in multi-page Streamlit apps (with query params)?

Hi Streamlit community,

Context & Goal:

We’re building a multi-page Streamlit app that requires user authentication. Our goals are:

  • Each user should have an isolated session (ideally, even across different tabs or browsers).

  • After login, users should be able to navigate between pages without losing their authenticated state.

  • Logging out in one tab/window should not affect other users or sessions.

  • We want to avoid using cookies for authentication (for security and isolation reasons).

What we tried:

  • After login, we generate a unique token for the user and redirect them to the main app page with the token and user_id as query parameters, e.g. /opening?user_id=…&token=…

  • On every page, we check the query parameters for the token and user_id to validate the session.

  • For navigation, we build links and redirects that always include the current user_id and token in the URL.

  • We tried both st.switch_page() and JavaScript redirects to /opening?user_id=…&token=…

  • We store the token/user_id in st.session_state for convenience, but always rely on query params for authentication.

The problem:

  • Query parameters are often lost when navigating between pages (especially when using st.switch_page()).

  • Even with JavaScript redirects, sometimes the parameters are not reliably available on the next page.

  • This causes users to be logged out or redirected to the login page unexpectedly.

  • We want to avoid using cookies for authentication, as they are shared across tabs and not per-user/per-tab.

What we want to achieve:

  • A robust, secure, and user-friendly authentication/session management system for Streamlit multi-page apps.

  • Per-user (and ideally per-tab) session isolation.

  • Reliable navigation between pages without losing authentication state.

  • No reliance on cookies for authentication.

Questions:

  1. Is there a better or more robust way to handle authentication/session management in Streamlit multi-page apps?

  2. Is there a way to reliably persist query parameters across page navigation (or a better alternative)?

  3. Are there any best practices or recommended patterns for this use case?

  4. Are there any known limitations or upcoming features in Streamlit that would help with this?

Any advice, examples, or pointers to best practices would be greatly appreciated!

Thank you!

Instead of putting the user token into a query parameter, just use and rely on Session State directly. Any hard refresh (or opening in a new tab) starts a new session. You won’t want to use Streamlit’s built-in authentication functionality since that does use a cookie, but since you already do the work of getting the user identity by some other means, just save that info in Session State. Whatever you save in Session State is unique to the session (which is unique to the tab) and not directly accessible to the user to copy like a query parameter is. If someone follows a Markdown link or does a hard refresh in their browser, they would restart their session, but as long as they are navigating the pages within Streamlit (like with st.switch_page or from the navigation widget), they will retain their current session.

Query parameters are designed to clear between pages to match the default behavior of query parameters in other systems, but we do have it on the roadmap to make some things easier with query parameters (like preserving them between pages). These new features aren’t available quite yet, though.