Hello,
I’m working on a Streamlit app deployed on Cloud Run, and I’m encountering a tricky issue with my cookie-based authentication. The problem seems to be how I’m setting and using cookies, leading to users logging in with credentials of previous users.
The Behavior:
- After a user authenticates, I set a cookie (
reauthentication_JADE_token
) to facilitate auto-login. - Problem: When another user accesses the app, the
check_cookies()
function finds the existing cookie and logs them in using the previous user’s information.
My Suspicion:
I think I might be misunderstanding how cookies should function within a multi-user Streamlit environment.
Questions:
- Cookie Best Practices: How can I effectively use cookies for authentication in a Streamlit app where multiple users might be accessing it concurrently?
- Scope and Isolation: Should cookies be user-specific? If so, how do I enforce that isolation in my code?
Any advice or insights on how to resolve this authentication conflict would be greatly appreciated!
Let me know if I should provide more code context.
Here my complete code for more context:
import jwt
import os
import streamlit as st
import extra_streamlit_components as stx
from datetime import datetime, timedelta
from functions.client_cache_functions import init_connection
from bson.objectid import ObjectId
def get_manager():
return stx.CookieManager()
cookie_manager = get_manager()
cookie_name = 'reauthentication_JADE_token'
cookie_expiry_days = 30
key = os.getenv('JADE_SECRET_KEY')
def _token_decode(token) -> str:
try:
return jwt.decode(token, key, algorithms=['HS256'])
except:
return False
def _token_encode() -> str:
return jwt.encode(
payload = {
'mongo_id': str(st.session_state['current_user']['_id']),
'exp_date': (datetime.now() + timedelta(days=cookie_expiry_days)).timestamp()
},
key=key,
algorithm='HS256')
def check_cookies():
token = cookie_manager.get(cookie_name)
if token is not None:
token = _token_decode(token)
if token is not False and token['exp_date'] > datetime.now().timestamp() and 'mongo_id' in token:
client = init_connection()
st.session_state["client"] = client
user = client.usersdb.users.find_one({"_id": ObjectId(token['mongo_id'])}, {"_id": 1, "name": 1, "email": 1, "avatar": 1, "admin": 1, "oauth_id": 1, "user_settings": 1, "stripe_settings": 1, "new_user": 1})
st.session_state["current_user"] = user
st.session_state["connected"] = True
return True
return False
def set_cookies():
token = _token_encode()
cookie_manager.set(cookie_name, token,
expires_at=datetime.now() + timedelta(days=cookie_expiry_days))
def delete_cookies():
st.query_params.clear()
cookie_manager.delete(cookie_name)