Skip to content

Authentication

Spera Alfredo Jeshoua edited this page May 14, 2025 · 5 revisions

VM Lab Project Structure Badge

Overview

Handles user registration, authentication, and role management.

Prerequisites

  • The database must be configured and working.
  • The .streamlit/secrets.toml file must be configured with all the necessary data and credentials to access the database and the cookie authentication details.

Libraries

This project uses Streamlit-Authenticator to manage authentication, that provides an Authenticator object.

Authenticator

The Authenticator provides pre-made functionalities:

  • Manages Login and Logout.
  • Provides a Login and Logout form frontend component.
  • Manages the authentication cookies for an automatic login.
  • Manages the current logged-in user's info.

It is stored in the Streamlit Session State at run-time, so it is sent to every browser session.

It also contains all the users credentials in a specific format (using the backend.models.user.to_credentials_dict() function), including the one that is currently logged in.

To properly integrate it into the system, there are auxiliary functions to create and retrieve this object.

Creation

This is a summary of the get_or_create_authenticator_object() function in backend/authentication/authenticator_creation.py.

flowchart TD

  %% Grouping related processes
  subgraph Database_Operations ["Database Operations"]
    GetDbConnection@{shape: cyl, label: "Get DB Connection"}
    FetchUsers@{label: "Fetch Users"}
    OrganizeCredentials@{shape: stadium, label: "Organize Credentials"}
  end
  style Database_Operations fill:#5f3c2599

  subgraph Session_State_Operations ["Session State Operations"]
    SetAuthenticator["Set Authenticator"]
    GetAuthenticator["Get Authenticator"]
  end
  style Session_State_Operations fill:#2a5d3399

  Start@{shape: circ, label: "Start"}
  Stop@{shape: dbl-circ, label: "Stop"}

  AuthenticatorExistsCheck{Authenticator Exists?}
  ReturnAuthenticator@{shape: stadium, label: "Return Authenticator"}
  GetAuthenticationCookie@{label: "Get Authentication Cookie"}
  InstantiateAuthenticator@{shape: stadium, label: "Instantiate Authenticator"}

  Start -->  GetAuthenticator
  GetAuthenticator --> AuthenticatorExistsCheck
  AuthenticatorExistsCheck -- "No, create the Authenticator Object" --> GetDbConnection
  GetDbConnection --> FetchUsers
  FetchUsers --> OrganizeCredentials
  OrganizeCredentials --> GetAuthenticationCookie
  GetAuthenticationCookie --> InstantiateAuthenticator
  InstantiateAuthenticator --> SetAuthenticator
  SetAuthenticator --> ReturnAuthenticator
  AuthenticatorExistsCheck -- "Yes" --> ReturnAuthenticator
  ReturnAuthenticator --> Stop
Loading

Manipulation

This mechanism updates the user's current data within the authenticator object whenever it is modified in the database (e.g., email or name change), to avoid data discrepancies during the current session.

Note

A simple refresh of the page would solve the problem (as it resets the session state), but updating in real time improves the user experience, avoiding disruptions in the flow of use.

These functions are in backend/authentication/authenticator_manipulation.py.

  • The add_new_user_to_authenticator_object() function does two jobs:

    • Adds a new user to the current session's authenticator object.
    • Edits an existing user in the current session's authenticator object.
  • The removal process is done in the remove_user_in_authenticator_object() function.

This is a summary of all three functions combined.

flowchart TD
  %% Subgraph: Session State Operations
  subgraph Session_State_Operations ["Session State Operations"]
    UpdateAuthenticator@{label: "Set Authenticator"}
  end
  style Session_State_Operations fill:#2a5d3399

  Start@{shape: circ, label: "Start"}
  Stop@{shape: dbl-circ, label: "Stop"}

  GetOrCreateAuthenticatorObject@{shape: subproc, label: "Get Or Create Authenticator Object"}
  CheckOperation{Operation}
  RemoveOldUser@{label: "Remove Old User"}
  EditRemoveOldUser@{label: "Remove Old User"}
  AddNewUser@{label: "Add New User"}
  Fork@{shape: fork}
  Join@{shape: fork}
  Merge@{shape: diamond, label: " "}

  Start --> GetOrCreateAuthenticatorObject
  GetOrCreateAuthenticatorObject --> CheckOperation
  CheckOperation --> Fork
  Fork -- "Add New User" --> AddNewUser
  Fork -- "Edit User" --> EditRemoveOldUser
  EditRemoveOldUser --> AddNewUser
  Fork -- "Remove User" --> RemoveOldUser
  AddNewUser --> Join
  RemoveOldUser --> Join
  Join --> Merge
  Merge --> UpdateAuthenticator
  UpdateAuthenticator --> Stop
Loading

Current User

Data getters

These functions are in backend/authentication/current_user_data.py.

They gather data about the current user from the session state:

  • Role
  • Full Name (First/Last name)
  • Username
  • Email
  • Login status (logged-in: True, not logged-in: False)

Note

Streamlit-Authenticator puts the role in the session state with key "roles".

Data manipulation

These functions are in backend/authentication/user_data_manipulation.py.

They act as an interface between the frontend and the Authenticator manipulation functions. Each one of these validates the input following the rules set in Streamlit-Authenticator's Validator class (e.g. string length, security requirements, etc).

These are the functions:

  • create_new_user: Creates a new user with add_new_user_to_authenticator_object()
  • edit_username: Edits a user's username with edit_user_in_authenticator_object()
  • edit_email: Edits a user's email with edit_user_in_authenticator_object()
  • edit_password: Edits a user's password with edit_user_in_authenticator_object()
  • edit_first_last_name: Edits a user's first and/or last name with edit_user_in_authenticator_object()
  • edit_role: Edits a user's role with edit_user_in_authenticator_object()

Important

Due to a technical limitation on how Streamlit-Authenticator works, after the user has edited its own username, they must be logged-out.

This is mostly due to the authentication cookie, and the fact that, for some reason, it cannot be edited. After logging back in, the cookie is updated with the new username.

This is a summary of all functions combined.

flowchart TD
  %% Subgraph: Session State Operations
  subgraph Database_Operations ["Database Operations"]
    GetDbConnection@{shape: cyl, label: "Get DB Connection"}
    UpdateDatabase@{label: "Update Database with the New Data"}
  end
  style Database_Operations fill:#5f3c2599

  Start@{shape: circ, label: "Start"}
  Stop@{shape: dbl-circ, label: "Stop"}

  ValidateInput@{label: "Validate All Inputs"}
  CheckValidation{Are all inputs valid?}
  AuthenticatorManipulation@{shape: subproc, label: "Authenticator Manipulation"}
  Error@{shape: odd, label: "Raise Exception"}

  Start --> ValidateInput
  ValidateInput --> CheckValidation
  CheckValidation -- "Yes" --> GetDbConnection
  GetDbConnection --> UpdateDatabase
  UpdateDatabase --> AuthenticatorManipulation
  AuthenticatorManipulation --> Stop
  CheckValidation -- "No" --> Error
  Error --> Stop
Loading

Clone this wiki locally