Skip to content

Commit

Permalink
v0.1.5 update
Browse files Browse the repository at this point in the history
1. Enhanced reauthentication cookie checking
2. Featured ability to import credentials and cookie settings from YAML configuration file
  • Loading branch information
mkhorasani committed May 25, 2022
1 parent 99c17d3 commit ac24465
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 33 deletions.
38 changes: 27 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,43 @@ import streamlit_authenticator as stauth

### 1. Hashing Passwords

* Initially define your users' names, usernames, and plain text passwords.
* Initially define your users' names, usernames, plain text passwords, and reauthentication cookie settings in a YAML configuration file.

```python
names = ['John Smith', 'Rebecca Briggs']
usernames = ['jsmith', 'rbriggs']
passwords = ['123', '456']
credentials:
names: ['John Smith', 'Rebecca Briggs']
usernames: ['jsmith', 'rbriggs']
passwords: ['123', '456'] # To be replaced with hashed passwords
cookie:
name: 'some_cookie_name'
key: 'some_signature_key'
expiry_days: 30
```

* Then use the hasher module to convert the plain text passwords to hashed passwords, and remove all plain text passwords from your source code.
* Then use the Hasher module to convert the plain text passwords to hashed passwords.

```python
hashed_passwords = stauth.Hasher(passwords).generate()
hashed_passwords = stauth.Hasher(['123', '456']).generate()
```

Finally replace the plain text passwords in the configuration file with the hashed passwords.

### 2. Creating Login Widget

* Subsequently use the hashed passwords to create an authentication object. Here you will need to enter a name for the JWT cookie that will be stored on the client's browser and used to reauthenticate the user without re-entering their credentials. In addition, you will need to provide any random key to be used to hash the cookie's signature. Finally, you will need to specify the number of days to use the cookie for, if you do not require passwordless reauthentication, you may set this to 0.
* Subsequently import the configuration file into your script to create an authentication object. Here you will need to enter a name for the JWT cookie that will be stored on the client's browser and used to reauthenticate the user without re-entering their credentials. In addition, you will need to provide any random key to be used to hash the cookie's signature. Finally, you will need to specify the number of days to use the cookie for, if you do not require passwordless reauthentication, you may set this to 0.

```python
authenticator = stauth.Authenticate(names, usernames, hashed_passwords,
'some_cookie_name', 'some_signature_key', cookie_expiry_days=30)
with open('../config.yaml') as file:
config = yaml.load(file, Loader=SafeLoader)

authenticator = stauth.Authenticate(
config['credentials']['names'],
config['credentials']['usernames'],
config['credentials']['passwords'],
config['cookie']['name'],
config['cookie']['key'],
config['cookie']['expiry_days']
)
```

* Then finally render the login module as follows. Here you will need to provide a name for the login form, and specify where the form should be located i.e. main body or sidebar (will default to main body).
Expand All @@ -57,7 +73,7 @@ name, authentication_status, username = authenticator.login('Login', 'main')
```python
if authentication_status:
authenticator.logout('Logout', 'main')
st.write('Welcome *%s*' % (name))
st.write(f'Welcome *{name}*')
st.title('Some content')
elif authentication_status == False:
st.error('Username/password is incorrect')
Expand All @@ -70,7 +86,7 @@ elif authentication_status == None:
```python
if st.session_state['authentication_status']:
authenticator.logout('Logout', 'main')
st.write('Welcome *%s*' % (st.session_state['name']))
st.write(f'Welcome *{st.session_state["name"]}*')
st.title('Some content')
elif st.session_state['authentication_status'] == False:
st.error('Username/password is incorrect')
Expand Down
10 changes: 6 additions & 4 deletions config.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
cookie:
name: 'some_cookie_name'
key: 'some_signature_key'
credentials:
names: ['John Smith', 'Rebecca Briggs']
usernames: ['jsmith', 'rbriggs']
passwords: ['123', '456']
passwords: ['$2b$12$RITgFvOneaLd7DvPS6UhZeRpZDPjnGvTKV.FCMNWRM92fz7ZapuC2',
'$2b$12$to1ADtwtCOFGMFNow7iJj.GjWWqy6FOEeeBjl/c.FmCZBSkf2bCr.']
cookie:
name: 'some_cookie_name'
key: 'some_signature_key'
expiry_days: 30
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name="streamlit-authenticator",
version="0.1.4",
version="0.1.5",
author="Mohammad Khorasani",
author_email="[email protected]",
description="A secure authentication module to validate user credentials in a Streamlit application.",
Expand Down
35 changes: 18 additions & 17 deletions streamlit_authenticator/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,10 @@ def login(self, form_name, location='main'):
if self.token is not False:
if not st.session_state['logout']:
if self.token['exp_date'] > datetime.utcnow().timestamp():
st.session_state['name'] = self.token['name']
st.session_state['authentication_status'] = True
st.session_state['username'] = self.token['username']
if 'name' and 'username' in self.token:
st.session_state['name'] = self.token['name']
st.session_state['username'] = self.token['username']
st.session_state['authentication_status'] = True

if st.session_state['authentication_status'] != True:
if location == 'main':
Expand Down Expand Up @@ -226,25 +227,26 @@ def logout(self, button_name, location='main'):
st.session_state['authentication_status'] = None

if not _RELEASE:

#hashed_passwords = Hasher(['123', '456']).generate()

with open('../config.yaml') as file:
config = yaml.load(file, Loader=SafeLoader)

hashed_passwords = Hasher(config['credentials']['passwords']).generate()

authenticator = Authenticate(
config['credentials']['names'],
config['credentials']['usernames'],
hashed_passwords,
config['credentials']['passwords'],
config['cookie']['name'],
config['cookie']['key'],
cookie_expiry_days=30
config['cookie']['expiry_days']
)

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

if authentication_status:
authenticator.logout('Logout', 'main')
st.write('Welcome *%s*' % (name))
st.write(f'Welcome *{name}*')
st.title('Some content')
elif authentication_status == False:
st.error('Username/password is incorrect')
Expand All @@ -255,12 +257,11 @@ def logout(self, button_name, location='main'):
# st.session_state['authentication_status'] to access the name and
# authentication_status.

#authenticator.login('Login', 'main')

#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')
# if st.session_state['authentication_status']:
# authenticator.logout('Logout', 'main')
# st.write(f'Welcome *{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')

0 comments on commit ac24465

Please sign in to comment.