Streamlit Authenticator
Streamlit Authenticator (current version 0.4.2) is a Python library that provides a secure authentication module to manage user access in Streamlit applications. It offers various widgets for login, logout, user registration, password reset, and user detail modification, supporting both local credential management and integration with OAuth2 providers. The library is actively maintained with frequent releases introducing new features and improvements.
Common errors
-
TypeError: Authenticate.init() got multiple values for argument 'cookie_expiry_days'
cause This error typically occurs when migrating from older versions (e.g., pre-0.4.0) where `Authenticate` expected separate arguments for credentials and cookie settings, to newer versions where a single `config` dictionary (or path) is preferred, or when attempting to pass the credentials list and then the config dict.fixEnsure you are initializing `stauth.Authenticate` with the correct signature for your version. For v0.4.x+, this usually means passing `config['credentials'], config['cookie']['name'], config['cookie']['key'], config['cookie']['expiry_days']` (or simply `config['credentials']` and other cookie params directly if not loading from file). -
TypeError: list indices must be integers or slices, not str
cause This error often arises when the `credentials` dictionary (or what's treated as credentials) is expected to be a dictionary of usernames but receives a list, especially if an older quickstart pattern is followed with a new library version.fixVerify that the `credentials` argument passed to `stauth.Authenticate` is a dictionary with 'usernames' as a key, and that 'usernames' itself maps to a dictionary of user objects, as per the current documentation's YAML structure. -
KeyError: 'credentials'
cause The authenticator attempts to access `config['credentials']` but the `config` dictionary (often loaded from YAML) is either empty, malformed, or the 'credentials' key is missing.fixDouble-check your `config.yaml` file structure. Ensure it has a top-level `credentials` key, which then contains the `usernames` dictionary with user details. Also, confirm the YAML file is correctly loaded. -
Login form did not render correctly. Check your configuration.
cause This message might appear if the `authenticator.login()` call is made with invalid parameters, or if the `authenticator` object itself was not initialized correctly, leading to the widget failing to render.fixReview the `stauth.Authenticate()` initialization parameters for correctness (credentials, cookie details). Also ensure your Streamlit environment is up-to-date and that `streamlit-authenticator` is installed correctly.
Warnings
- breaking The `Authenticate` class constructor parameters changed significantly between versions (e.g., from v0.3.x to v0.4.x). The `credentials` parameter now expects a dictionary or a path to a config file, rather than separate lists for names, usernames, and hashed passwords.
- breaking The `pre_authorized` list was removed from the `Authenticate` class constructor in v0.4.1 and is now handled directly by the `register_user` widget as a parameter.
- gotcha For multi-page Streamlit applications, it is crucial to pass the `authenticator` object to each page (e.g., via `st.session_state`) and ensure `key` parameters are unique for widgets across pages to prevent `DuplicateWidgetID` errors.
- gotcha Enabling two-factor authentication or email features (e.g., for password reset) in v0.4.2 requires registering for a free API key and passing it to the `Authenticate` constructor via the `api_key` parameter or in the config file.
Install
-
pip install streamlit-authenticator
Imports
- Authenticate
from streamlit_authenticator import Authenticate
import streamlit_authenticator as stauth authenticator = stauth.Authenticate(...)
- Hasher
from streamlit_authenticator.utilities import Hasher
import streamlit_authenticator as stauth hashed_passwords = stauth.Hasher(passwords).generate()
Quickstart
import streamlit as st
import streamlit_authenticator as stauth
import yaml
from yaml.loader import SafeLoader
# --- User Credentials & Cookie Configuration (typically from config.yaml) ---
config = {
'credentials': {
'usernames': {
'john_doe': {
'email': 'john@example.com',
'name': 'John Doe',
'password': 'abc' # Will be hashed if auto_hash is True
},
'rebecca_smith': {
'email': 'rebecca@example.com',
'name': 'Rebecca Smith',
'password': 'def'
}
}
},
'cookie': {
'expiry_days': 30,
'key': 'random_signature_key_here',
'name': 'my_app_cookie'
}
}
# To simulate loading from file (for demonstration, usually you'd load from actual config.yaml)
# In a real app, you would load this from a persistent config.yaml file.
# Example: with open('config.yaml') as file:
# config = yaml.load(file, Loader=SafeLoader)
# Hash passwords only if not already hashed (auto_hash=True by default in Authenticate)
# You can pre-hash them explicitly if you wish:
# for username, user_data in config['credentials']['usernames'].items():
# user_data['password'] = stauth.Hasher([user_data['password']]).generate()[0]
# --- Initialize Authenticator ---
authenticator = stauth.Authenticate(
config['credentials'],
config['cookie']['name'],
config['cookie']['key'],
config['cookie']['expiry_days'],
# api_key=os.environ.get('STREAMLIT_AUTH_API_KEY', None) # For 2FA/email features
)
# --- Login Widget ---
name, authentication_status, username = authenticator.login('Login', 'main')
if authentication_status == False:
st.error('Username/password is incorrect')
elif authentication_status == None:
st.warning('Please enter your username and password')
elif authentication_status:
# --- Main App Content for Authenticated Users ---
authenticator.logout('Logout', 'main')
st.write(f'Welcome *{name}*')
st.title('Application Content')
st.write('This content is only visible to authenticated users.')
# Example of accessing user info from session state
# st.write(f"Current user: {st.session_state['username']}")
# st.write(f"Authentication status: {st.session_state['authentication_status']}")