New Component: Streamlit-Authenticator, a secure authenticaton module to validate user credentials in a Streamlit application

Dear @Gedanggoreng currently streamlit_authenticator has no provisions for sending an email to the user with a forgotten username/password. The widget will return the email associated with the forgotten username/password and you will have to arrange for that information to be sent to the user’s email yourself.

How did you resolve this issue ?
I am having the same problem

As mentioned previously - currently streamlit_authenticator has no provisions for sending an email to the user with a forgotten username/password. The widget will return the email associated with the forgotten username/password and you will have to arrange for that information to be sent to the user’s email yourself.

I’m getting: ā€œUsername/password is incorrectā€ every time. I’m printing some variables to have a better understanding, but I’m not able to fix it:

I can share everything because I’m just starting with this. I’m trying to log with:
Login: me@mail.com
Password: 123

config.yaml

credentials:
  usernames:
    myself:
      email: me@mail.com
      name: Me
      password: $2b$12$AlQ63O8OQMQ0Fu/8/6jyYudiDI2MQtXVgV/m1uffW0PPJ4kNXCwLS
cookie:
  expiry_days: 30
  key: some_signature_key
  name: some_cookie_name
preauthorized:
  emails:
  - me@mail.com

main.py

import streamlit as st
import css
import prompts
import model
import yaml
import os
import streamlit_authenticator as stauth
from streamlit_authenticator import Authenticate
from yaml import SafeLoader

#####

cwd = os.getcwd()
with open(cwd + '/' + 'config.yaml') 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')

##### Some defs #####

if authentication_status:
  authenticator.logout('Logout', 'main')
  with st.sidebar:
    ### UI ELEMENTS
elif authentication_status is False:
    st.error('Username/password is incorrect')
elif authentication_status is None:
    st.warning('Please enter your username and password')

pip list | grep streamlit

extra-streamlit-components   0.1.56
streamlit                    1.17.0
streamlit-authenticator      0.2.1

Hash generator

print(stauth.Hasher(['123']).generate())

Please enter the username i.e. myself, not the email.

It worked, I’m such a newbie :sweat_smile:

Thank you.

I got the same error, and for me its because I didn’t put the hashed password in the config.yaml file (running the code doesn’t mean you already stored the hashed password, you need to copy paste it into the config.yaml file)
image

Let me know, if this helps you :slight_smile: .

Screenshot 2023-03-15 172506

Is it possible to use password only w/o names & username?

No, both of these fields are required at the moment.

Hello, thank you for your amazing streamlit component. I wonder if there is a simple way to automatically log out after some time of inactivity (ex: 30min of inactivity).

Hi @AnthonyBrossault, you are most welcome. That is an excellent idea for a subsequent release, please feel free to add it to the GitHub list of issues and I will try to implement it in the near future. In the meantime, you can try to hack it yourself by clearing the session state variable associated with the authentication object after a set period of time, and removing associated reauthentication cookies saved on the browser. Removing keys from session state should be as straightforward as writing del st.session_state[ā€˜authentication_status’]. You can read more about clearing the cookies here. To measure the passage of time you can make use of a library such as Streamlit Autorefresh. Cheers.

You can use any Gmail account for this by creating and using and app password to your email account as in the following link (https://support.google.com/accounts/answer/185833?visit_id=638215606016109598-1972104324&p=InvalidSecondFactor&rd=1). Once you’ve done it, use the following code:

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

def send_password_email(sender_email, sender_password, recipient_email, password):
    # Gmail SMTP server configuration
    smtp_server = 'smtp.gmail.com'
    smtp_port = 587

    # Email content
    subject = 'Secure Password Delivery'
    body = f'Your password is: {password}'

    # Create a multipart email message
    message = MIMEMultipart()
    message['Subject'] = subject
    message['From'] = sender_email
    message['To'] = recipient_email

    # Attach the email body as plain text
    message.attach(MIMEText(body, 'plain'))

    try:
        # Establish a secure connection to the SMTP server
        server = smtplib.SMTP(smtp_server, smtp_port)
        server.starttls()
        # Login to the SMTP server with the application-specific password
        server.login(sender_email, sender_password)
        # Send the email
        server.sendmail(sender_email, recipient_email, message.as_string())
        # Close the SMTP connection
        server.quit()
        print('Email sent successfully.')
    except Exception as e:
        print(f'Error occurred while sending the email: {e}')

# Example usage
sender_email = 'your_sender_email@gmail.com'
sender_password = 'your_application_specific_password_generated by Gmail'
recipient_email = 'recipient_email@example.com'
password = 'password_to_send'

send_password_email(sender_email, sender_password, recipient_email, password)