Giter Site home page Giter Site logo

mkhorasani / streamlit-authenticator Goto Github PK

View Code? Open in Web Editor NEW
1.2K 1.2K 212.0 711 KB

A secure authentication module to validate user credentials in a Streamlit application.

License: Apache License 2.0

Python 100.00%
authentication python streamlit streamlit-component

streamlit-authenticator's Introduction

Hi there ๐Ÿ‘‹

๐ŸŒฑ Projects:

โšก Employment:

  • Software Developer at Iberdrola - designing, developing, and implementing software solutions for the advancement of renewable energy systems and services. My work requires me to develop cloud-native data analytics applications and to design robotic systems. This entails creating client and server-side software, producing high-fidelity CAD/CAM assemblies, and automating sub-systems with micro-controllers.

๐Ÿ“• Latest Blog Posts

๐Ÿ“ซ Contact:

LinkedIn Medium GrabCAD

streamlit-authenticator's People

Contributors

mkhorasani avatar velicanu avatar vince-weka avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

streamlit-authenticator's Issues

Unsafe characters allowed in username creation

Currently there is no restriction on characters in a username, which can result in security issues if the value of the username is not handled properly post authentication. Example:

Screen Shot 2023-03-15 at 8 43 48 AM

Would you be open to allowing only alphanumeric + _ , or alternatively to let the auth module take a username validator as an optional parameter to decide the allowed character set?

ValueError: Please enter hashed passwords... even though it is already hashed.

First of all, thanks for the awesome module. I get this error even though the password I used is hashed. I can login just fine on the second attempt though.

ValueError: Please enter hashed passwords and not plain text passwords into the 'authenticate' module.
Traceback:
File "/Users/server/opt/miniconda3/envs/parakeet/lib/python3.9/site-packages/streamlit/script_runner.py", line 379, in _run_script
    exec(code, module.__dict__)
File "/Users/server/Parakeet/main.py", line 64, in <module>
    main()
File "/Users/server/Parakeet/main.py", line 54, in main
    draw_sidebar()
File "/Users/server/Parakeet/main.py", line 41, in draw_sidebar
    name, authentication_status = authenticator.login('Login','sidebar')
File "/Users/server/opt/miniconda3/envs/parakeet/lib/python3.9/site-packages/streamlit_authenticator/__init__.py", line 188, in login
    raise ValueError("Please enter hashed passwords and not plain text passwords into the 'authenticate' module.")

Return user email, Name for new user

Hi,
Is there a way that we can get the email address and the name of the newly registered user without modifying the package code. Currently is returns if a new user has successfully created account or not.

TypeError: __init__() got multiple values for argument 'cookie_expiry_days'

Hi,

We were able to use the following code with version 0.1.5 but after the update it started throwing this error. Please see the code below.

names = ['NAME']
usernames = ['USERNAME']
passwords = ['PASSWORD']

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')

Feature - Disallow registration if email is already taken.

Currently the registration only blocks registration if the username is already taken, but it allows to register with the same email infinite time, which is not good.
Perhaps you could add a feature that doesnt allow to use the same email more than once.

auth with st.set_page_config

When i define code for authentication in my def main() in wihch st.set_page_config(layout="wide"). My app not working.
def main():
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:
    current_plan = data.get_current_capacity_plan()
    setup_multipage(current_plan)
    refresher.start()
elif authentication_status == False:
    st.error('Username/password is incorrect')
elif authentication_status == None:
    st.warning('Please enter your username and password')

st.set_page_config(
    page_title='app_name',
    layout='wide',
) 

That in error trace
StreamlitAPIException: set_page_config() can only be called once per app, and must be called as the first Streamline command in your script.

when st.set_page_config is commented out everything works

ideas? i dont understand where st.set_page_config can called. Or how i can define default page config for authentication

Constant authentication_status == False

hi , i was just working with streamlit-authenticator and was making a login page usng config.yaml , but it always outputing the authentication_status as False , however i have done exactly the same as there was in docs. Please help me to resolve this.
Also while deploying it on streamlit cloud, it was not getting the credentials from the repo .

DuplicateWidgetID: There are multiple identical st.button widgets with the same generated key.

When following and try running code from github. Everything function except there's an error of streamlit.

My Analysis and solution: st.button widget required assigned "different" keyname and the backend code use the same keyname, resulting in an error.

error msg from cli:
'''
streamlit.errors.DuplicateWidgetID: There are multiple identical st.button widgets with the
same generated key.

When a widget is created, it's assigned an internal key based on
its structure. Multiple widgets with an identical structure will
result in the same internal key, which causes this error.

To fix this error, please pass a unique key argument to
st.button.
'''

SNAG-0086

Newer version breaks with cookies from old version

Hi, I was using version 0.1.0, and when updated to version 0.1.4, because I and other users already have some cookies in the browsers, the code breaks when it tries to access the field username from the cookies.

The traceback is

File "/code/app/utils/misc.py", line 35, in authentication_workflow
    name, authentication_status, username = authenticator.login("Login", "sidebar")
File "/usr/local/lib/python3.8/site-packages/streamlit_authenticator/__init__.py", line 163, in login
    st.session_state['username'] = self.token['username']

Configuration file support for unicode

Congratulations on your great project.

I noticed an issue when the config.yaml contains unicode characters.
For example when using the reset password feature the yaml load and dump works perfectly but the process escapes all unicode chars. Unfortunately this cancels the yaml file human readability.

An simple solution would be to just use the allow_unicode parameter when dumping the config back to the filesystem:

with open('../config.yaml', 'w') as file:
yaml.dump(config, file, default_flow_style=False, allow_unicode=True, sort_keys=False)

How does it sound?
:)

Keep up the good work!

NameError: name 'SafeLoader' is not defined

ymal config loader might depreciated? I try running the code and there's an error about "Loader=SafeLoader" I switch to new code below and found working.

with open('user.ymal') as file:
# config = yaml.load(file, Loader=SafeLoader) # previous code, not working
config = yaml.safe_load(file) # new code (working)

SNAG-0087

streamlit.errors.StreamlitAPIException: Values for st.button, st.download_button, st.file_uploader, and st.form cannot be set using st.session_state.

When I run my code, Streamlit throws an API exception. Here is the code that is concerns this problem:

import sqlite3

from CRM.main import crm, stauth
from projectBoard.toDo import *

connproj = sqlite3.connect('projectBoard/projectData.db')
cproj = connproj.cursor()
conncrm = sqlite3.connect('CRM/userData.db')
ccrm = conncrm.cursor()
st.session_state.update(st.session_state)
selectedPage = st.sidebar.selectbox("Page", ["Project Board", "CRM (unfinished)"])
loginbutton = st.sidebar.button("Log in")
if loginbutton:
    crm(conncrm, ccrm)
    selectedPage = "Log In"
elif selectedPage == "Project Board":
    projectboard(cproj, connproj)
import streamlit as st
import streamlit_authenticator as stauth

from CRM.setupdb import loaddb


def crm(conn, c):
    st.title("Log In")
    loaddb(conn, c)
    print(c.execute("SELECT email FROM userTable").fetchall())
    authenticator = stauth.Authenticate(c.execute("SELECT email FROM userTable").fetchall(), c.execute("SELECT username FROM userTable").fetchall(), c.execute("SELECT password FROM userTable").fetchall(), "CRM", "CRM")
    name, authentication_status = authenticator.login('Login', 'main')

Get passwords from Database

Hi,

I am trying to get my passwords with a select query from the database, but when I pass it to the Hasher module, I get an error:

File "/home/appuser/venv/lib/python3.9/site-packages/streamlit_authenticator/init.py", line 37, in hash

return bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode()

AttributeError: 'tuple' object has no attribute 'encode'

What type of object should be passed to the Hasher module?

I am very new to python and will appreciate your help tremendously.

Any way to enable enter key?

Hi,
I want to press the enter key on the keyboard for authentication instead of clicking the login button.
Any way to enable this function?

Code executed 3 times when login

Hello,
When you log in with Streamlit-Authenticator, the code is executed 3 times.
I added a print('test') command and I can see 'test' 3 times in the console.

I'm using version 0.2.1.

import streamlit as st
import streamlit_authenticator as stauth
import yaml

st.set_page_config(page_title='Auth', layout='wide')

# Load Authenticator Configuration
with open('config.yaml') as file:
    config = yaml.load(file, Loader=stauth.SafeLoader)

# Authenticator Parameters
authenticator = stauth.Authenticate(
    config['credentials'],
    config['cookie']['name'],
    config['cookie']['key'],
    config['cookie']['expiry_days']
)

name, authentication_status, username = authenticator.login('Login', 'main')

if st.session_state["authentication_status"]:
    authenticator.logout('Logout', 'main')
    st.write(f'Welcome *{st.session_state["name"]}*')
    st.title('Some content')
    print("test")
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')

After logging in, the problem doesn't occur again.

Automatically save and load hashed_passwords as a file

Hi,

First of all thank you for your work on Streamlit-Authenticator, it's a very appreciated module :)

I have a feature request to ease its use.
It turns out that once the hashed_passwords are generated with .Hasher.generate, I end up saving it as a txt file and then load it afterwards for the Authenticate method.

It would be easier to add the possibility to automatically save the hashed_passwords as a file (with the .generate method), and load it (with the .Authenticate method).

The workflow would look like this:

names = ['John Smith', 'Rebecca Briggs']
usernames = ['jsmith', 'rbriggs']
passwords = ['123', '456']

hashed_passwords = stauth.Hasher(passwords).generate(folder_path="path_to_folder")

A .key file is then automatically generated at path_to_folder/hashed_passwords1546.key
1546 here is a random number generated when .Hasher.generate() is called.

Then, when you need to use hashed_passwords, you can use the legacy way:

authenticator = stauth.Authenticate(
    names, usernames, 'some_cookie_name',
    'some_signature_key', cookie_expiry_days=30,
    hashed_passwords=hashed_passwords,
)

Or you can alternatively use the saved hashed_passwords1546.key file:

authenticator = stauth.Authenticate(
    names, usernames, 'some_cookie_name', 
    'some_signature_key', cookie_expiry_days=30
    hashed_passwords_path="path_to_folder/hashed_passwords1546.key"
)

I already implemented most of it for my use, so if you think this a good idea, I could raise a PR.

Best regards,
Alex

Case Sensitive Username

Amazing work on this module, thanks!!

It seems that the usernames are case sensitive.
As most users (that I know of) are not used to having case sensitive usernames, this will likely confuse them.

Is there any way to set the module to compare the username as case insensitive?

Not able to create a new account using register_user

I am new to streamlit. I want to have a login and signup functionality in my application. I am able to successfully implement login using the username and password stored in the config.yaml file. However, I am not able to properly implement the register_user or reset/update the password. The program runs smoothly and I get the 'registration successful' message but when I try to log in using the new credentials I get the 'incorrect username/password' error.

image

image

Can I block a new login, when a user is already logged in?

Hello, I have a streamlit webapp that uses streamlit-authenticator and it works just fine, but we have seen some 'collisions' when two users are logged in a the same time (same variable names, different values, erase each other temporary files, and so on). Is there a way to block the new login to be sure that only one user can login at the same time?

Clean up README.md

Some possible corrections:

  1. Say somewhere one needs to install pyyaml and import yaml
  2. In the first code snippet in 'Creating a login widget', replace Loader=SafeLoader by Loader=yaml.SafeLoader

Or something like that as I struggled to realize the above from the README.md. It may be obvious to a lot of folks but it was not to me.

I could do it myself but I am hesitant as I don't want to interfere in your README. Package is great by the way! Thanks!

Request for help

Respected sir,
Kindly help me how to increase the size of message input box to 1 GB from 1MB. I am able to do it for file uploader, but not for message input box.

Regards,
Satish

Feature - Only allow users within a certain domain to create an account

Small lift here. But it would be great if we could define who can create a user account. This would allow users to make a streamlit application public, and then allow everyone from their organization to create individual accounts.

Also happy to integrate this if you are willing to accept it :D

Reuse username after login

Hi,

Do you know how it would be possible to reuse the username after the user logins? I want to pass it onto a query to search in a pandas dataframe so I can display information pertaining only to that user.

Thanks,

login cache error

Hi,
i'm developing 2 different apps with 2 different sets of users.
App 1 works fine. App 2 shows the following error

KeyError: 'st.session_state has no key "$$GENERATED_WIDGET_ID-637ca37599f40177530b03ec7d367849-None". Did you forget to initialize it? More info: https://docs.streamlit.io/library/advanced-features/session-state#initialization'

With some trial and error, seems like the browser has the app 1 user list cached and apply's it to app 2, could it be?
Or is unrelated?
thanks

code to reproduce

def get_login():
    filename = 'app_users_config.yaml'
    with open(filename) as file:
        config = yaml.load(file, Loader=SafeLoader)
    authenticator = Authenticate(
        config['credentials'],
        config['cookie']['name'],
        config['cookie']['key'],
        config['cookie']['expiry_days'],
        config['preauthorized']
    )
    name, authentication_status, username = authenticator.login('Login', 'main')
    if authentication_status is None:
        st.warning('Please enter your username and password')
        login = False
    elif not authentication_status:
        st.error('Username/password is incorrect')
        login = False
    elif authentication_status:
        login = True
    else:
        raise ValueError(f"{authentication_status=}")
    return login, username

def app():
    st.title('test)
    login, username = get_login()
    if not login:
        return
    st.text('Running')

option to disable hashing

Hi, thanks for creating this component! I find the cookie authentication very useful.

I am storing the config as a streamlit secret so it is not necessary to hash the passwords. Is it possible to disable this? Right now I am getting an invalid salt error when I try to use plain text passwords.

Feature - Store YAML file in a remote data store

It would be terrific is the user credentials could be stored in a remote data store (Deta, Mongo, etc).

I would be happy to integrate this feature if you are interested in having it incorporated.

Failure with cookie authentication patch required as workaround

I am using streamlit-Authenticator which works almost fine except that cookie faster reauthentication never worked.

I am using streamline 1.20.0 and streamlit-authenticator 0.2.1 with python 3.10.6

I've done some analysis and found that the problem is in the module streamlit_authenticator/authenticate.pyat line #106.

The function call :

self.token = self.cookie_manager.get(self.cookie_name)

do NOT return the token value but return None (I checked that the browser effectively sent the cookie properly).

I replaced this line by:

allCookies = self.cookie_manager.get_all()
self.token = allCookies.get(self.cookie_name, None)

and then the correct token value is recovered and processed as expected allowing me to recover authentication.

Any idea why the get do not work ?

Extra-Streamlit-Components breaks Authenticator?

Had installed authenticator, everything set up and working fine, then decided to install extra components to take a look and now login for throws this error over and over. "Invalid Salt""

The only other things I can think that may have caused this was wiping the cache, but pretty confident I had done that already with no issues.

Any ideas for a fix?

The three-level credential dictionary is vey painful to use

Hi @mkhorasani , thank you for sharing this amazing package with us.
I found the new way of adding credentials very painful to use, especially for those who retrieve user information from a remote database.

  1. I don't think it's a good idea to create a three-level credential dictionary. It takes the users extra work to convert the data they retrieved from the database to the format that meets the requirement.
    As you can see below, the 'usernames' key in the dictionary is useless. Also, the keys at the second level of the dictionary are the usernames. The varying keys at this level make it a lot more difficult to do certain operations
    {'usernames': {'jsmith': {'email': '[email protected]', 'name': 'John Smith', 'password': 123}, 'rbriggs': {'email': '[email protected]', 'name': 'Rebecca Briggs', 'password': 456}}}
    Is there a specific reason for not using a much simpler structure like below?
    {'username': 'jsmith', 'email': '[email protected]', 'name': 'John Smith', 'password': 123}

  2. the Hashing passwords part also became very difficult to use. Previously, we only needed to provide a list of hashed passwords to the Authenticator. Now, we need to first retrieve the original passwords from the very painful 3-level dictionary and then hash them and then put them back. It feels like torture.

Logout requires two presses

When using the log out button it always seems to require at least two presses to fully logout back to the login screen.

st.button calling authenticator.forgot_username returns None and empty tuple

Still learning streamlit, so maybe a newbie question:
Following your README example, I create the streamlit_local_auth.py
As you can see from the code, I use a st.button to call forgot_username_button method.

def forgot_username_button(auth):
    try:
        username_forgot_username, email_forgot_username = auth.forgot_username('Find my username')

        if username_forgot_username:
            return st.success('Username sent securely')
            # Username to be transferred to user securely
        elif username_forgot_username == False:
            return st.error('Email not found')
        print(username_forgot_username, email_forgot_username)
    except Exception as e:
        return st.error(e)
    

if not authentication_status:
    if st.button("forgot username"):
        forgot_username_button(authenticator)

Unfortunately, it seems username_forgot_username, email_forgot_username returned from auth.forgot_username method are somehow None and ""(empty string). Even if I pass authenticator as a parameter!

Please help. Thx a lot!

Example APP using streamlit-authenticator

Hi @mkhorasani,

Thank you for this amazing component!

It would be helpful if you created an example app using streamlit-authenticator so it is easier to quickstart using this component. I am having some issues using the component.

Best,
Ryan

Logging users

I'm looking for a way to track the users login by writing a new line to a db table on each successful login.
Triggering the write after if authentication_status: will trigger everytime the app gets rerun, not just on login.

Is there a way to get just the "original" login?

Implementing a "register user" fails

I've added a widget to allow user to register (per the doc):
try:
if authenticator.register_user('Register user', preauthorization=False):
st.success('User registered successfully')
except Exception as e:
st.error(e)

But when loading the app, I get:
"Pre-authorization argument must not be None"

streamlit == 1.9.2
streamlit-authenticator == 0.2.1
OS == Ubuntu 16.04
Python == 3.6.13

Screen Shot 2022-11-30 at 6 18 04 PM

compatibility issue with chrome extension

Hi,

I found that if I enable the evernote clipper in the chrome, I can't login for some reason, and nothing is displayed in the terminal.

Other extension have nothing to do with the compatibility issue.

Would you please check it out?

Custom fields in reg form

Good day. Is it possible to add additional (custom) fields to the registration form? I edited your code for my application, but it's the wrong way ))) It would be very nice to be able to add some number of input fields without having to fix the code arbitrarily manually.
Thank you for your job! Well done!

Customize "Username", "Password", "Login"

Hi @mkhorasani, thanks a lot for maintaining this awesome module! I'd like to be able to customize the labels for the two text_inputs and for the button. Specifically, I'd make them lower caps so that they fit in with the rest of the naming pattern in the screenshot below. I could do a PR myself, as I feel there are literally 4 lines of code to change. Let me know what you think!

# current
name, authentication_status = authenticator.login('login', 'sidebar')

# suggestion
name, authentication_status = authenticator.login('login', 'sidebar', 'username', 'password', 'login') # where the new ones have defaults

Edit: Same for "Logout" would be nice, too.

Screenshot from 2022-01-06 10-16-41

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.