mkhorasani / Streamlit-Authenticator

A secure authentication module to manage user access in a Streamlit application.
Other
1.53k stars 246 forks source link

Using the Authenticator with credentials stored in a remote database #193

Open njt1980 opened 1 month ago

njt1980 commented 1 month ago

Hi - Can we use the Authenticator when credentials are stored in a remote database?

P.S - Did not find a place to post question, hence posting as an issue. Sorry if that is not per guidelines.

mkhorasani commented 1 month ago

Hi @njt1980, thank you for reaching out. It can be done and perhaps this video can help. In the future, I plan on releasing a version that supports hosting the credentials on a remote database. Until then please stay tuned!

njt1980 commented 1 month ago

Thank you for the prompt reponse. I kind of put together some skeleton code for a login page. It does not throw any error, but I see that, the execution seems to be stopping at name, authentication_status, username = authenticator.login({'sidebar'}) and the print statement after that does not seem to be executing. Just wanted to check if I am doing anything wrong. Any direction would be great.

Below is the full code for the page


import streamlit as st
import streamlit_authenticator as stauth
import os
import sqlite3

#Connect to remote database and retrieve user credentials if available
def get_user_credentials(username):
    connection = sqlite3.connect(r"C:\Users\reservation_system.db")
    cursor = connection.cursor()

    #Query to get user details
    cursor.execute("SELECT name,hashed_password FROM credentials WHERE username = ?",(username,))
    user = cursor.fetchone()
    connection.close()
    if user:
        return user[0],user[1]
    return None, None

# Assume the user enters their username and password in a login form
input_username = st.text_input("Username")
input_password = st.text_input("Password", type="password")

if st.button("Login"):
    name, hashed_password = get_user_credentials(input_username)
    print("name :",name)
    print("input_username :", input_username)
    print("hashed_password :",hashed_password)

    if name and hashed_password:
        print("Creating authenticator object...")
        # Authenticate the user with the retrieved hashed password
        # authenticator = stauth.Authenticate([name], 
        #                                     [input_username], 
        #                                     [hashed_password], 
        #                                     "user_cookie", 
        #                                     "cookie_key",
        #                                     cookie_expiry_days=1)

        authenticator = stauth.Authenticate({"usernames":{
                                                input_username:{
                                                        "name":name,
                                                        "password":hashed_password
                                                    }}
                                            }, 
                                            "user_cookie", 
                                            "cookie_key",
                                           )

        # Perform authentication
        print("Authenticating...")
        name, authentication_status, username = authenticator.login({'sidebar'})
        print("Authentication status :",authentication_status)

        if st.session_state['authentication_status']:
            authenticator.logout()
            st.write(f'Welcome *{st.session_state["name"]}*')
            st.title('Some content')
        elif st.session_state['authentication_status'] is False:
            st.error('Username/password is incorrect')
        elif st.session_state['authentication_status'] is None:
            st.warning('Please enter your username and password')
        else:
            st.error("Username not found")
brdemorin commented 3 weeks ago

Incredible package, so appreciated. Associated with this would be the ability to send email/username input and hashed password input to the authenticator. That way I can call remote db to retrieve a single user with one hashed password for the authenticator to match against instead of a big payload of all users

That or allow the authenticator to give us the email input to make a small payload db call before matching passwords?

mkhorasani commented 3 weeks ago

Incredible package, so appreciated. Associated with this would be the ability to send email/username input and hashed password input to the authenticator. That way I can call remote db to retrieve a single user with one hashed password for the authenticator to match against instead of a big payload of all users

That or allow the authenticator to give us the email input to make a small payload db call before matching passwords?

This is in the pipeline and I hope to release it in Q4 of this year. Please stay tuned!

brdemorin commented 3 weeks ago

Awesome. And if the ability is there to debundle username/email and password inputs from the authenticator so they can be sent as inputs to a non-render version of it, that allows us to use OAuth for authentication then use your authenticator to handle setting the cookies and session states

mkhorasani commented 3 weeks ago

Awesome. And if the ability is there to debundle username/email and password inputs from the authenticator so they can be sent as inputs to a non-render version of it, that allows us to use OAuth for authentication then use your authenticator to handle setting the cookies and session states

Yeap, I will consider serving the logic as a service running on a backend server that the user can interface with.