Streamlit is a powerful framework for building data applications in Python, but it doesn’t include built-in authentication. This means you’ll need to implement your own security layer to protect sensitive data and control access to your applications. Whether you’re building internal tools, client-facing dashboards, or public applications, adding proper authentication is crucial for maintaining security and controlling access to your Streamlit apps.

This guide walks through several authentication methods for Streamlit apps, from basic password protection to integration with third-party authentication providers such a Auth0. We’ll cover implementation details, tradeoffs between different approaches, and best practices for keeping your application secure. You’ll learn how to implement simple password-based authentication for basic protection, integrate with enterprise authentication systems for more robust security, and understand the security implications of each approach.

We’ll explore practical examples to help you choose and implement the right authentication solution for your specific needs. Whether you’re looking for a quick solution to protect an internal dashboard or need enterprise-grade security for a production application, this guide will provide you with the knowledge and tools to properly secure your Streamlit applications.

By the end of this guide, you’ll understand the various authentication options available, their implementation details, and how to choose the right approach based on your security requirements and technical constraints.

Ploomber Cloud

The easiest way to protect your app is with Ploomber Cloud, since this service manages the authentication process before your users can access your application. This service allows you to easily deploy your Streamlit application with your chosen authentication method, using the most up-to-date security processes, without the need to edit your application’s code.

Password Protection

It’s as simple as choosing your username and password. This setup eliminates the common barriers that many developers face when trying to protect their applications, making it accessible to users of all skill levels.

With this option, you’re not just adding a layer of protection; you’re doing it in the simplest way possible with the best security, since all credentials are encrypted. This means that your username and password are not just hidden but transformed into a format that is extremely difficult for unauthorized parties to decode. This level of security provides peace of mind, knowing that your application’s access controls can’t easily be bypassed or compromised.

Another bonus of using our service is that this authentication method is framework-agnostic. This means if you decide to branch out and use different web frameworks for your future projects, you can still utilize the same straightforward method to add authentication. This compatibility saves you time and effort, as you won’t need to learn a new process or integrate different security measures each time you explore a new framework.

Learn more about deploying Streamlit apps in our documentation

Auth0 Authentication

Note that Ploomber Cloud’s password protection works for a single set of credentials, meaning that while it is perfect for sharing a Dashboard securely with your team, all team member will need to know the username and the password. However, if you need a more sophisticated way of securing your application you can use the Auth0 integration. Auth0 is a platform that allows developers to implement secure login processes and control access to applications, and combining this one with the Ploomber Cloud platform will allow you to authenticate user from multiple platform, like @gmail.com, or even @yourcompany.com if Auth0 support your Authentication mechanisme.

Advantages of using auth0:

  • Single Sign-On (SSO): allows users to log into multiple applications using the same login credentials.
  • Social login: allows users to log in using their existing credentials from another account, such as Facebook, Google, or Amazon.
  • Passwordless connections: allows users to log in using a one-time password (OTP) sent via SMS to their phone or their email address.
  • Multi-Factor Authentication: acts as an extra layer of security that requires users to provide more than one piece of verifying information before logging in.
  • Account recovery: allows them to regain access to their account if the user has forgotten their password or lost access to one of their devices.

Ploomber Cloud enables you to easily secure your Streamlit applications using auth0.

Let’s look at a sample application in which we read the HTTP header X-Auth-Name from the current session:

import streamlit as st

header_name = st.context.get("X-Auth-Name")
st.write(header_name)

To learn more about authenticating this app using Auth0 check out this blog.

Manually adding an authentication form

Global Password

Streamlit offers a rather straightforward approach to adding authentication to applications, especially useful for developers looking to implement a basic level of security without getting into the complexities of Single Sign-On (SSO). However, it’s important to note that Streamlit’s own documentation cautions users that this level of security is not as robust as authenticating with an SSO provider. This acknowledgment is refreshingly honest, yet it flags a potential area of concern for applications requiring more stringent security measures

Nevertheless, let’s see how such a process can be implemented. First, we need to store the password somewhere. One option is to use .streamlit/secrets.toml, where each value will be accessible with st.secrets['SECRET_KEY']. This is highly specific to Streamlit. Another approach is to use environment variables. To do so, we can create a file named .env and save our password in it:

# .env
STREAMLIT_PASSWORD=streamlit123

In our application, we can use python-dotenv to load this file and make the key-value pairs accessible like any other environment variable.

Remember to add your secret files to your .gitignore, so these secrets won’t be accessible through your versioning system.

# app.py
import hmac
import os
import streamlit as st
from dotenv import load_dotenv

# Load the .env
load_dotenv()

def check_password():
    """Returns `True` if the user had the correct password."""
    def password_entered():
        # If you use .streamlit/secrets.toml, replace os.environ.get with st.secrets["STREAMLIT_PASSWORD"]
        if hmac.compare_digest(st.session_state["password"], os.environ.get("STREAMLIT_PASSWORD", "")):
            st.session_state["password_correct"] = True
            del st.session_state["password"]
        else:
            st.session_state["password_correct"] = False

    # Return True if the password is validated.
    if st.session_state.get("password_correct", False):
        return True

    st.info(f"Password: {os.environ.get('STREAMLIT_PASSWORD', '')}")
    # Show input for password.
    st.text_input(
        "Password", type="password", on_change=password_entered, key="password"
    )
    if "password_correct" in st.session_state:
        st.error("😕 Password incorrect")
    return False

if not check_password():
    st.stop()

st.write("I am a protected text 🔐")

To deploy your app with a password, you can simply enter your key-value pair from the .env file as an environment variable, like shown below:

Individual Username & Password

Streamlit’s second option presented is to allow users to have their own username and password.

This second methodology remains fundamentally the same, storing credentials in the app secrets and making them available for verification in the cloud. This method addresses some of the limitations of the global password approach by providing a way to revoke or change access on a per-user basis without impacting all users. However, it still doesn’t match the security and flexibility offered by more advanced authentication services, and the need for manual management of user credentials might deter more advanced users or those with higher security needs.

Nevertheless, let’s once again look at how we can implement this system. This one is almost the same as previously shown, but we now have multiple Username - Password pairs, which we need to compare the user input to.

  • The first option is to use the Streamlit approach to store these by having the values in the .streamlit/secrets.toml, but this will restrict how and where you will be able to deploy your application since we will need this specific file which should never be stored alongside your application.

  • The second option is to again use the environment variable approach as a way to store these values.

  • The last option would be to store these values in a Database, allowing a more central approach to password management, but be aware, this method isn’t secure out of the box as well.

Let’s see how to implement the second option.

# .env
# _STREAMLIT_PASSWORD suffix so there is no collision with other env variable
GUILLAUME_STREAMLIT_PASSWORD=streamlit456
EDUARDO_STREAMLIT_PASSWORD=streamlit789
# app.py
import os
import hmac
import streamlit as st
from dotenv import load_dotenv

load_dotenv()

def check_password():
    """Returns `True` if the user had a correct password."""

    def login_form():
        """Form to collect username & password"""
        with st.form("Credentials"):
            st.text_input("Username", key="username")
            st.text_input("Password", type="password", key="password")
            st.form_submit_button("Log in", on_click=password_entered)

    def password_entered():
        """Checks whether a password entered by the user is correct."""
        if os.environ.get(f"{st.session_state["username"].upper()}_STREAMLIT_PASSWORD") \
            and hmac.compare_digest(
            st.session_state["password"],
            os.environ.get(f"{st.session_state["username"].upper()}_STREAMLIT_PASSWORD")
        ):
            st.session_state["password_correct"] = True
            # Don't store the username or password in the session
            del st.session_state["password"]
            del st.session_state["username"]
        else:
            st.session_state["password_correct"] = False

    # Return True if the username + password is validated.
    if st.session_state.get("password_correct", False):
        return True

    # Show inputs for username + password.
    login_form()
    if "password_correct" in st.session_state:
        st.error("😕 User not known or password incorrect")
    return False

if not check_password():
    st.stop()

# Main Streamlit app starts here
st.write("I am a protected text 🔐")

The end application will be the following, try it out with guillaume and streamlit456

We can deploy this the same way as previously, and we can store the user credentials as environment variables on any platform.

To sum up, Streamlit presents a handy, if basic, solution for adding authentication to Streamlit apps. Its major selling points are simplicity and ease of use, ideally suited for developers quickly safeguarding less critical applications that are on an internal network. Nonetheless, for those developing applications where security is a must, Streamlit’s authentication methods might fall short, emphasizing the trade-off between convenience and comprehensive security. Despite these caveats, Streamlit provides a straightforward path to authentication while openly acknowledging its limitations.

Streamlit-Authenticator

To add more security to the authentication process, as well as more features, like allowing users to register themselves and change their passwords, we can use the streamlit-authenticator package by Mohammad Khorasani. With it, we can also have different privileges for user-specific access controls.

To get started with this package, we need to provide a config file, which will be used to store and retrieve the user’s personal information.

cookie:
  expiry_days: 30
  # Must be a string
  key: some_signature_key
  name: some_cookie_name
credentials:
  usernames:
    jsmith:
      email: jsmith@gmail.com
      # Will be managed automatically
      failed_login_attempts: 0
      first_name: John
      last_name: Smith
      # Will be managed automatically
      logged_in: False
      # Will be hashed automatically
      password: abc
      # Optional
      roles:
      - viewer
    guillaume:
      email: guillaume@ploomber.io
      # Will be managed automatically
      failed_login_attempts: 0
      first_name: Guillaume 
      last_name: Thibault
      # Will be managed automatically
      logged_in: False
      # Will be hashed automatically
      password: streamlit123
      roles: # Optional
      - admin
      - editor
      - viewer

We can now edit our application to ask for the username & password, and only show the content once the user is properly authenticated.

import streamlit as st
import streamlit_authenticator as stauth
import yaml
from yaml.loader import SafeLoader

# Load the config
with open('./credentials.yml') as file:
    config = yaml.load(file, Loader=SafeLoader)

# Pre-hashing all plain text passwords once
stauth.Hasher.hash_passwords(config['credentials'])

# Save the Hashed Credentials to our config file
with open('./credentials.yml', 'w') as file:
    yaml.dump(config, file, default_flow_style=False)

authenticator = stauth.Authenticate(
    config['credentials'],
    config['cookie']['name'],
    config['cookie']['key'],
    config['cookie']['expiry_days']
)

try:
    auth = authenticator.login('main')
except Exception as e:
    st.error(e)

# All the authentication info is stored in the session_state
if st.session_state["authentication_status"]:
    # User is connected
    authenticator.logout('Logout', 'main')
elif st.session_state["authentication_status"] == False:
    st.error('Username/password is incorrect')
    # Stop the rendering if the user isn't connected
    st.stop()
elif st.session_state["authentication_status"] == None:
    st.warning('Please enter your username and password')
    # Stop the rendering if the user isn't connected
    st.stop()


st.title('🔐 Protected Application')
st.write(f'Welcome *{st.session_state["name"]}*')

The end application will be the following, try it out with guillaume and streamlit456

With this, we now have a more robust password system, with some of the essential security policies needed, like hashing the password, which makes it really difficult to infer its plain text representation (needed to get a match; even by knowing the hash, it can’t be used to authenticate a user).

We can also control which information the user has access, by looking at its roles, with:

st.session_state['roles']

And also programmatically reset a lost password, as well as a username:

try:
    username_of_forgotten_password, \
    email_of_forgotten_password, \
    new_random_password = authenticator.forgot_password()
    if username_of_forgotten_password:
        st.success('New password to be sent securely')
        # The developer should securely transfer the new password to the user.
    elif username_of_forgotten_password == False:
        st.error('Username not found')
except Exception as e:
    st.error(e)

And finally, the package also provides a way to let user registering themself:

try:
    email_of_registered_user, \
    username_of_registered_user, \
    name_of_registered_user = authenticator.register_user(pre_authorized=config['pre-authorized']['emails'])
    if email_of_registered_user:
        st.success('User registered successfully')
except Exception as e:
    st.error(e)

The streamlit-authenticator package eliminates the need for manual user management code. All the essential functionality - from user registration and authentication to password recovery - is handled automatically through its built-in methods.

However, it’s important to note a limitation: this authentication system is standalone and not connected to enterprise authentication services. If you need to integrate with your organization’s central authentication system (like Microsoft Entra, Oauth, or SSO), you’ll want to explore the enterprise authentication options covered in the section below.

Central Authentication Provider

SAML

Dedicated Blog Post for Streamlit + SAML

Microsoft Entra ID

Dedicated Blog Post for Streamlit + Microsoft Entra ID

Google Authentication

Dedicated Blog Post for Streamlit + Google Auth (with auth0)

Enterprise Authentication Integration

For organizations requiring robust, enterprise-grade security, integrating your Streamlit app with central authentication providers offers the highest level of security and user management capabilities.

SAML Authentication

SAML (Security Assertion Markup Language) remains a widely used standard for enterprise authentication. When you integrate SAML with your Streamlit app, you get:

  • Single Sign-On (SSO) capability across all your organization’s applications
  • Centralized user management and access control
  • Enhanced security through standardized authentication protocols
  • Detailed audit logs of all authentication attempts

While implementing SAML requires more initial setup than basic password protection, it provides enterprise-grade security that scales with your organization. For a detailed walkthrough of implementing SAML in your Streamlit app, check out our comprehensive guide on Streamlit + SAML integration.

Microsoft Entra ID Integration

For organizations using Microsoft’s ecosystem, integrating with Microsoft Entra ID (formerly Azure Active Directory) is a natural choice. This integration offers:

  • Seamless authentication for users already working with Microsoft tools
  • Advanced security features like conditional access and multi-factor authentication
  • Integration with Microsoft’s comprehensive identity management system
  • Automated user provisioning and deprovisioning

Learn more about implementing this solution in our detailed Streamlit + Microsoft Entra ID guide.

Google Authentication & OAuth

Google’s authentication system is widely trusted and offers a familiar experience for users. Implementing Google authentication through the OAuth protocol, which Auth0 provides a simple experience to integrate, allows you to leverage standard authentication flows. Adding this to your app will allow:

  • A familiar login experience using Google credentials
  • Robust security backed by Google’s infrastructure and OAuth standards
  • Support for both personal and organizational Google accounts
  • Ability to extend to other OAuth providers like GitHub, Facebook, or Twitter

This option is particularly appealing for organizations using Google Workspace or those wanting to provide a streamlined login experience for users with Google accounts, while maintaining the flexibility to add other OAuth providers in the future. For implementation details, visit our Streamlit + Google Auth integration guide.


When choosing between these enterprise authentication options, consider:

  • Your organization’s existing identity management infrastructure
  • Compliance requirements and security policies
  • User experience preferences
  • Technical expertise available for implementation and maintenance