File size: 1,870 Bytes
c8a8b27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
"""OPTIONAL login wrapper (streamlit-authenticator).

This is NOT wired into app.py by default, so the core demo always runs. To turn
it on, add these two lines at the top of app.py (right after the imports):

    from src.auth import require_login
    name, username, roles = require_login()

Security notes:
  * Passwords are bcrypt-hashed by the library (auto_hash=True). For real
    security, pre-hash with `python hash.py` and store ONLY the hash in
    auth_config.yaml — never commit plain-text passwords to a public repo.
  * The login version's `login()` signature has changed across releases; this
    reads auth state from st.session_state (the stable pattern). Pin your
    installed version and test the flow locally.
"""
import yaml
from yaml.loader import SafeLoader

import streamlit as st
import streamlit_authenticator as stauth


def get_authenticator(path="auth_config.yaml"):
    with open(path) as f:
        config = yaml.load(f, Loader=SafeLoader)
    return stauth.Authenticate(
        config["credentials"],
        config["cookie"]["name"],
        config["cookie"]["key"],
        config["cookie"]["expiry_days"],
        auto_hash=True,
    )


def require_login(path="auth_config.yaml"):
    """Render the login widget; stop the app unless the user is authenticated.

    Returns (name, username, roles) once logged in.
    """
    authenticator = get_authenticator(path)
    authenticator.login(location="main")

    status = st.session_state.get("authentication_status")
    if status is False:
        st.error("Invalid username or password.")
        st.stop()
    if status is None:
        st.info("Please log in to continue.")
        st.stop()

    authenticator.logout("Logout", "sidebar")
    return (st.session_state.get("name"),
            st.session_state.get("username"),
            st.session_state.get("roles") or [])