I'm building a basic streamlit app. In order to validate user credentials, I'm using the authentification module of streamlit. Only one problem, the code does not work !
TypeError: Authenticate.init() got multiple values for argument 'cookie_expiry_days'
Traceback:
File "C:\Users_M92\Desktop\Coding\Python\Projects\Personal1\venv\lib\site-packages\streamlit\scriptrunner\script_runner.py", line 557, in _run_script exec(code, module.dict)
File "app.py", line 23, in authenticator = stauth.Authenticate(names, usernames, hashed_passwords,
By the way, I used the same code described here in the official documentation :
import streamlit as st
import streamlit_authenticator as stauth
names = ['John Smith', 'Rebecca Briggs']
usernames = ['jsmith', 'rbriggs']
passwords = ['123', '456']
hashed_passwords = stauth.Hasher(passwords).generate()
authenticator = stauth.Authenticate(names, usernames, hashed_passwords,
'some_cookie_name', 'some_signature_key', cookie_expiry_days=30)
name, authentication_status, username = authenticator.login('Login', 'main')
if authentication_status:
authenticator.logout('Logout', 'main')
st.write('Welcome *%s*' % (name))
st.title('Some content')
elif authentication_status == False:
st.error('Username/password is incorrect')
elif authentication_status == None:
st.warning('Please enter your username and password')
if st.session_state['authentication_status']:
st.write('Welcome *%s*' % (st.session_state['name']))
st.title('Some content')
elif st.session_state['authentication_status'] == False:
st.error('Username/password is incorrect')
elif st.session_state['authentication_status'] == None:
st.warning('Please enter your username and password')
When I removed the argument cookie_expiry_days=30
, I get this error instead :
TypeError: list indices must be integers or slices, not str
File"C:\Users_M92\Desktop\Coding\Python\Projects\Personal1\venv\lib\site-packages\streamlit_authenticator\authenticate.py",line 36, in __init__self.credentials['usernames'] = {key.lower(): value for key, value in credentials['usernames'].items()}
Do you have any idea why I keep getting these errors ?
So since 2 days later and still no reply from OP :p here's what I found after checking out 0.2.1 as ferdy pointed out...
the new format requires a credentials dictionary, the example given is like this
credentials:
usernames:
jsmith:
email: jsmith@gmail.com
name: John Smith
password: '123' # To be replaced with hashed password
rbriggs:
email: rbriggs@gmail.com
name: Rebecca Briggs
password: '456' # To be replaced with hashed password
cookie: expiry_days: 30
key: some_signature_key
name: some_cookie_name
preauthorized: emails:
- melsby@gmail.com
but since that wants a yaml and I basically had it all set up the old way (based on Coding is Fun's youtube tutorial), i wanted to just pass the credentials to the authenticator directly, so if your original code is like this...
authenticator = stauth.Authenticate(names, usernames, passwords, "app_home", "auth", cookie_expiry_days=30)
what you want is a dictionary like this
credentials = {
"usernames":{
usernames[0]:{
"name":names[0],
"password":passwords[0]
},
usernames[1]:{
"name":names[1],
"password":passwords[1]
}
}
}
Then you pass that to authenticator like so...
authenticator = stauth.Authenticate(credentials, "app_home", "auth", cookie_expiry_days=30)
so just to clarify your resulting credentials dictionary will look something like this...
credentials = {
"usernames":{
"jsmith92":{
"name":"john smith",
"password":"$2b$12$TSuKwWML0EpbohBQgHx4p8E5q"
},
"tturner":{
"name":"timmy turner",
"password":"$2b$12$asdaUduuibuEIyBUBHASD896a"
}
}
}
As you may note I've not included the cookie part in the dictionary (as they state you should in the config.yaml) and it still works just fine
Now of course you can fill in these variables in a loop based on how many items you have in each list (names, passwords, usernames) but if you just want to quickly test one or two sets of credentials this is a quick and easy way to do so.
For reference here is the loop that i used to create the final credentials dictionary dynamically based on any number of credentials in the users, names, and passwords lists...
credentials = {"usernames":{}}
for un, name, pw in zip(usernames, names, passwords):
user_dict = {"name":name,"password":pw}
credentials["usernames"].update({un:user_dict})
authenticator = stauth.Authenticate(credentials, "app_home", "auth", cookie_expiry_days=30)
First initialise the credentials dictionary with the usernames key and an empty dictionary as the value.
Then zip the credentials (usernames, names, password) together and loop them. Note for my example - un means username, pw means password
Then we add each user_dict to the credentials dictionary as a value under the "usernames" key by using the update function. Note - be sure to wrap the dictionary in {} in the update part i.e. .update({un:user_dict})
You may also want to add a logout button once the user has verified since the login form disappears once the user is authenticated (30 day cookies) making it practically impossible to test if you don't have one.
You can do that with a simple if statement, using the authentication_status from earlier like so...
if authentication_status == True:
authenticator.logout("logout","main")
Sorry its long but figured id update to include the actual loop i used, here is the code I used which is working, in it's entirety for anyone who wants it
# my class function which makes a call to a database and returns a list of lists (nested list), of usernames, names, and passwords
users = usr.get_all_users_credentials()
# the code mentioned above
usernames = [user[1] for user in users]
names = [user[2] for user in users]
passwords = [user[3] for user in users]
credentials = {"usernames":{}}
for un, name, pw in zip(usernames, names, passwords):
user_dict = {"name":name,"password":pw}
credentials["usernames"].update({un:user_dict})
authenticator = stauth.Authenticate(credentials, "app_home", "auth", cookie_expiry_days=30)
name, authentication_status, username = authenticator.login("Login", "main")
if authentication_status == True:
authenticator.logout("logout","main")