Streamlit Guide
Streamlit Authentication
Add login to your Streamlit app — three approaches, from simple to enterprise-ready.
Last updated: October 2026 · Tested with Streamlit 1.40+
Quick answer: For quick internal tools, use streamlit-authenticator with hashed passwords in secrets.toml. For enterprise SSO, use Streamlit's built-in st.login() with OIDC. For simple demos, a password check against a secret works. Never expose your app publicly without auth if it uses paid APIs.
Three Approaches — Pick One
| Approach | Best For | Complexity |
|---|---|---|
| Password secret | Personal demos, prototypes | Very simple |
| streamlit-authenticator | Internal tools, small teams | Simple |
| Native OIDC (st.login) | Enterprise SSO, public apps | Moderate |
Option A: Simple Password (Quickest)
For personal demos, a single password check is enough:
# .streamlit/secrets.toml
APP_PASSWORD = "mysecretpassword"
# app.py
import streamlit as st
def check_password():
if "authenticated" not in st.session_state:
st.session_state.authenticated = False
if not st.session_state.authenticated:
password = st.text_input("Password", type="password")
if st.button("Login"):
if password == st.secrets["APP_PASSWORD"]:
st.session_state.authenticated = True
st.rerun()
else:
st.error("Wrong password")
st.stop()
check_password()
st.write("Welcome to the secret app!")
Not recommended for teams: This approach has one shared password and no user tracking. Use it only for personal use or demos.
Option B: streamlit-authenticator (Best for Teams)
pip install streamlit-authenticator
Generate hashed passwords:
import streamlit_authenticator as stauth
hashed = stauth.Hasher(["pass1", "pass2"]).generate()
print(hashed)
# ['$2b$12$...', '$2b$12$...']
Add config to .streamlit/secrets.toml:
[credentials.usernames.alice]
name = "Alice"
password = "$2b$12$..."
email = "alice@example.com"
[credentials.usernames.bob]
name = "Bob"
password = "$2b$12$..."
email = "bob@example.com"
[cookie]
name = "streamlit_auth"
key = "some-random-secret-key"
expiry_days = 30
Then in your app:
import streamlit as st
import streamlit_authenticator as stauth
authenticator = stauth.Authenticate(
st.secrets["credentials"].to_dict(),
st.secrets["cookie"]["name"],
st.secrets["cookie"]["key"],
st.secrets["cookie"]["expiry_days"],
)
name, auth_status, username = authenticator.login()
if auth_status:
authenticator.logout(location="sidebar")
st.write(f"Welcome, {name}!")
# Your app content here
elif auth_status is False:
st.error("Username or password incorrect")
elif auth_status is None:
st.warning("Please log in")
💡 Why this is great: Passwords are hashed with bcrypt, sessions persist across page reloads via cookies, and you get a built-in logout button. All in one package.
Option C: Native OIDC (Enterprise SSO)
Streamlit now has built-in OIDC support for Google, Microsoft, Okta, and Auth0:
# .streamlit/secrets.toml
[auth]
redirect_uri = "https://your-app.streamlit.app/oauth2callback"
cookie_secret = "random-32-char-string"
[auth.google]
client_id = "your-client-id"
client_secret = "your-client-secret"
server_metadata_url = "https://accounts.google.com/.well-known/openid-configuration"
Then in your app:
import streamlit as st
if not st.user.is_logged_in:
st.login()
if st.user.is_logged_in:
st.write(f"Welcome, {st.user.name}!")
st.write(f"Email: {st.user.email}")
# Your app content here
if st.sidebar.button("Log out"):
st.logout()
The user is authenticated via Google (or your OIDC provider). No passwords to manage.
Gate Your App Content
Whatever approach you pick, the pattern is the same:
if not authenticated:
st.warning("Please log in to continue")
st.stop()
# All your app content below this line
st.title("My App")
st.write("Sensitive data...")
st.stop() halts execution. Nothing below it renders until the user is authenticated.
🛡️ Security Best Practices
- Never hardcode passwords or API keys in your code.
- Always hash passwords (bcrypt via streamlit-authenticator, or use OIDC).
- Use
.streamlit/secrets.tomllocally and Streamlit Cloud secrets in production. - Add secrets to
.gitignore. Rotate keys if you accidentally commit them. - Enable HTTPS — Streamlit Cloud does this automatically.
- For public apps with paid APIs, always require authentication.
- Log out sessions after a reasonable expiry (30 days is common).
- Consider rate limiting on the login form to prevent brute-force attacks.
The most common mistake: Deploying a chatbot that uses your OpenAI key without any authentication. Anyone can find the URL and run up your bill. Add auth before sharing publicly.
❓ Frequently Asked Questions
How do I add authentication to Streamlit?
Use the streamlit-authenticator package for username/password auth, or use Streamlit's built-in OIDC support for Google/Microsoft SSO. For simple internal tools, st.secrets-based password checks work fine.
What is streamlit-authenticator?
streamlit-authenticator is a community package that provides a ready-made login widget, password hashing, cookie-based sessions, and user management for Streamlit apps.
Does Streamlit have built-in authentication?
Streamlit has built-in OIDC support for enterprise SSO (Google, Microsoft, Okta). For simple username/password auth, use streamlit-authenticator. For public apps, add OIDC to prevent API abuse.
How do I protect secrets in Streamlit?
Store secrets in .streamlit/secrets.toml locally and in the Streamlit Cloud dashboard for deployed apps. Never commit secrets to Git. Use st.secrets['KEY'] to access them.
Can I add a login page to Streamlit?
Yes. Use streamlit-authenticator's login widget or Streamlit's native st.login() to build a login page. Gate the rest of your app behind the authentication check.