🔐 Lesson: Add User Authentication (Username & Password)


🎯 Goal

Allow users to:

  • 🔑 Sign up and log in securely

  • 🙍 Personalize chat history & memory

  • 🗂️ Store uploads and messages per user


✅ Options for Auth in Streamlit

Method Tools Notes
🟩 Built-in Streamlit Login st.session_state + manual form Easy, secure for basic needs
🟦 Firebase Auth Firebase + Pyrebase External service, email/password + social login
🟥 Streamlit Auth Component streamlit-authenticator Clean UI, YAML config, hashed passwords

We’ll start with the easiest and safest:

✅ Option 1: Manual Auth with Hashed Passwords (Secure & Simple)


🧩 Step 1: Install bcrypt for Secure Password Hashing

pip install bcrypt

📁 Step 2: Create users.json

{
  "ronny": {
    "password": "$2b$12$XhR/1xY13FzmXaYgBJoRauKMRpHf2sfIE9fhE0DRp/V4QxRgWPRPq"
  }
}

The value is a hashed password ("1234" hashed with bcrypt)

You can hash your own with this snippet:

import bcrypt
password = b"1234"
hashed = bcrypt.hashpw(password, bcrypt.gensalt())
print(hashed)

📜 Step 3: Add Login UI to Your app.py

import json
import bcrypt

def load_users():
    with open("users.json", "r") as f:
        return json.load(f)

def authenticate(username, password):
    users = load_users()
    if username in users:
        stored = users[username]["password"].encode()
        return bcrypt.checkpw(password.encode(), stored)
    return False

# Login form
if "user" not in st.session_state:
    st.subheader("🔐 Login to Your AI Agent")
    with st.form("login"):
        username = st.text_input("Username")
        password = st.text_input("Password", type="password")
        submit = st.form_submit_button("Login")

        if submit:
            if authenticate(username, password):
                st.session_state.user = username
                st.success(f"Welcome, {username}!")
                st.experimental_rerun()
            else:
                st.error("❌ Invalid username or password")
    st.stop()

Now all authenticated users will enter the app normally.


🧠 Step 4: Personalize Per-User Memory & Files

Update your paths like this:

user_folder = os.path.join("user_data", st.session_state.user)
os.makedirs(user_folder, exist_ok=True)

# Save files per user
uploaded_path = os.path.join(user_folder, file.name)

Use user_folder to:

  • Save uploaded documents

  • Store vector DB (user_data/ronny/db_memory)

  • Store chat logs


🗂️ Optional: Show User’s Past Chats

chat_file = os.path.join(user_folder, "chat_log.txt")

def log_chat(user_input, ai_output):
    with open(chat_file, "a") as f:
        f.write(f"You: {user_input}nBot: {ai_output}nn")

Show in sidebar:

if os.path.exists(chat_file):
    with open(chat_file, "r") as f:
        st.sidebar.markdown("### 💬 Previous Chats")
        st.sidebar.text(f.read())

✅ Summary

✅ Secure login using username + hashed password
✅ Session stored with st.session_state.user
✅ All files, memory, and chat logs are stored per user


 

26