A simple username/password database authentication solution for Streamlit

Overview

Simple Authentication for Streamlit Apps

A simple username/password database authentication solution for Streamlit

Arvindra Sehmi, CloudOpti Ltd. | Website | LinkedIn

Updated: 31 August, 2021


TL;DR: This is a simple username/password login authentication solution using a backing database. Both SQLite and Airtable are supported.

Quick start

To get started immediately with a SQLite database, follow these steps:

  1. Clone this repo

  2. Copy the sample environment settings file env.sample to .env

  3. Install requirements

    pip install -r requirements.txt

  4. Initialize the SQLite database and create some users (including at least one super user)

    streamlit run admin.py

  5. Finally, run the test application

    streamlit run app.py

Introduction

This is not an identity solution, it's a simple username/password login authentication solution using a backing database inspired by this post (written by madflier) over in the Streamlit discussion forum.

I've previously implemented an authentication and identity solution: Streamlit component for Auth0 Authentication. That's definitely the solution I'd recommend but feel that the Streamlit community has been slow to take it up. Perhaps it's considered to be something for big enterprise applications? Given how easy it is to use Auth0 that's not true. Or perhaps, because Streamlit components can get complicated and require separate Streamlit and web apps to make them work, something else with fewer moving parts is more desirable? I don't know for sure what the blockers are and will be producing some tutorials on Auth0 + Streamlit integration soon to help educate our community.

In the meantime, I think a solution like madflier's will be more palatable for many folks getting started with Streamlit and needing authentication? To fill this gap, I thought I'd build on his application and improve its flexibility and production readiness. Though my aim is contrary to madflier's objectives around simplicity, there are so many requests for simple database-backed authentication in the Streamlit discussion forum that I felt it was worth the effort to take his solution several steps further. As an honorary member of Streamlit's Creators group I recently had the opportunity to work on my idea in a Streamlit-internal hackathon and this is what I'll describe here. Allow me to both apologise to madflier for the many changes I've made to his design and thank him for the initial spark! :-)

What I've built

I've redesigned the original solution and added the following functionality:

  • Session state support so logins survive Streamlit's top-down reruns which occur in it's normal execution.

  • Support for logout, authenticated check, and a requires_auth function decorator to protect areas of your own apps, e.g. secure pages in a multi-page Streamlit application.

    • See how requires_auth is used to secure superuser functions in auth.py. You can do the same in your code.
  • Built-in authentication/login status header widget that will sit nicely in most Streamlit apps.

  • Refactored the SQLite local DB dependency in the main auth module so it uses a DB provider design pattern implementation.

  • Given the refactoring, I added a simple factory for multiple provider implementations, so different persistence technologies could be used, for example a cloud DB.

    • In fact, I built an Airtable cloud database provider which can replace SQLite as an alternative.
  • The abstract provider interface is super simple and should allow almost any database to be adapted, and it works fine for this specific auth use case in the implementations I created.

    • Some Streamliters have mentioned Google Sheets and Firebase - yep, they should be easy.
  • Passwords are stored hashed (MD5) & encrypted (AES256 CBC Extended) in the database, not as plain text. Note, the password is never sent to the browser - it's retrieved, decrypted and matched on the Streamlit server - so is quite secure. I'm definitely following OWASP best practice.

  • Configuration has been externalized for things like database names and locations, cloud service account secrets, api keys, etc. The configuration is managed in a root .env and env.py files, and small Python settings files for the main app (app_settings.py), and each provider implementation (settings.py).

  • There's just enough exception handling to allow you to get a handle on your own extension implementations.

  • I use debugpy for remote debugging support of Streamlit apps, and include a little module that makes it work better with Streamlit's execution reruns.

All code is published under MIT license, so feel free to make changes and please fork the repo if you're making changes and submit pull requests.

If you like this work, consider clicking that star button. Thanks!

Demos

Test application

The Streamlit app app.py illustrates how to hook authlib into your Streamlit applications.

app.py

Database Admin

The Streamlit app admin.py illustrates how to auto-start authlib's superuser mode to create an initial SQLite database and manage users and user credentials.

admin.py

Installation and running the app

To install the pre-requisites, open a console window in the root folder and run:

$ pip install -r requirements.txt

To run the sample application, open a console window in the root folder and run:

# Starts the app on the default port 8765
$ streamlit run app.py

# I use a specific port 8080 like this
$ streamlit run --server.port 8080 app.py

To run the DB Admin application, open a console window in the root folder and run:

$ streamlit run admin.py

Getting started with a SQLite database

There's nothing you need to do as SQLite is part of Python (I use version 3.8.10). The admin.py Streamlit application will handle creating a database and users table for you, and then allow you to populate users, and edit existing databases.

  1. First, assign the STORAGE value in the .env file in the application root folder.

For example:

.env file

# Options are 'SQLITE', 'AIRTABLE'
STORAGE='SQLITE'

A full example (which includes Airtable and encryption key settings) is available in env.sample.

  1. Then, you must run the admin app as shown above to create your initial SQLite database!

Getting started with an Airtable database

How to create an Airtable

  1. First, login into or create a (free) Airtable account.

  2. Next, follow these steps to create an Airtable:

  • Create a database (referred to as a base in Airtable) and a table within the base.
  • You can call the base profile and the table users
  • Rename the primary key default table field (aka column) to username (field type 'Single line text')
  • Add a password field (field type 'Single line text')
  • Add a su (superuser) field (field type 'Number')

Finding your Airtable settings

  1. You can initially create and then manage your API key in the 'Account' overview area
  2. For your base (e.g. profile) go to the 'Help menu' and select 'API documentation'
  3. In 'API documentation' select 'METADATA'
  4. Check 'show API key' in the code examples panel, and you will see something like this:
EXAMPLE USING QUERY PARAMETER
$ curl https://api.airtable.com/v0/appv------X-----c/users?api_key=keyc------X-----i
  • keyc------X-----i is your 'API_KEY' (also in your 'Account' area)
  • appv------X-----c is your 'BASE_ID',
  • users will be your 'TABLE_NAME'

Configuring Airtable's app settings

Assign these values to the keys in the Airtable section of the .env file in the application root folder.

For example:

.env file

# Options are 'SQLITE', 'AIRTABLE'
STORAGE='AIRTABLE'

# Airtable account
AIRTABLE_API_KEY='keyc------X-----i'
AIRTABLE_PROFILE_BASE_ID = 'appv------X-----c'
USERS_TABLE = 'users'

A full example (which includes SQLite and encryption key settings) is available in env.sample.

That's it! You're ready now to use the admin application or Airtable directly to manage the credentials of your users.

TODO

Caveat emptor: You're free to use this solution at your own risk. I have a few features on my wish list:

  • In addition to username, password, and su I want to add additional useful user data to the database: logged_in, expires_at, logins_count, last_login, created_at, updated_at.
  • Provide a Streamlit component wrapper to make it easy to pip install (st_auth maybe??)
  • JavaScript API library making it easy to use the authentication DB in custom component implementations.
  • Would be nice to enhace the library and make an Auth0 provider (leverage my Auth0 component).
  • Deploy the demo app on Streamlit sharing and use it's secrets store instead of my .env solution.
Owner
Arvindra
Arvindra
MikroTik Authentication POCs

Proofs of concept which successfully authenticate with MikroTik Winbox and MAC Telnet servers running on RouterOS version 6.45.1+

Margin Research 56 Dec 08, 2022
Easy and secure implementation of Azure AD for your FastAPI APIs 🔒 Single- and multi-tenant support.

Easy and secure implementation of Azure AD for your FastAPI APIs 🔒 Single- and multi-tenant support.

Intility 220 Jan 05, 2023
Brute force a JWT token. Script uses multithreading.

JWT BF Brute force a JWT token. Script uses multithreading. Tested on Kali Linux v2021.4 (64-bit). Made for educational purposes. I hope it will help!

Ivan Å incek 5 Dec 02, 2022
Extending the Django authentication system with a phone verification step.

Extending the Django authentication system with a phone verification step.

Miguel Grinberg 50 Dec 04, 2022
Pingo provides a uniform API to program devices like the Raspberry Pi, BeagleBone Black, pcDuino etc.

Pingo provides a uniform API to program devices like the Raspberry Pi, BeagleBone Black, pcDuino etc. just like the Python DBAPI provides an uniform API for database programming in Python.

Garoa Hacker Clube 12 May 22, 2022
A JSON Web Token authentication plugin for the Django REST Framework.

Simple JWT Abstract Simple JWT is a JSON Web Token authentication plugin for the Django REST Framework. For full documentation, visit django-rest-fram

Jazzband 3.2k Dec 28, 2022
Object Moderation Layer

django-oml Welcome to the documentation for django-oml! OML means Object Moderation Layer, the idea is to have a mixin model that allows you to modera

Angel Velásquez 12 Aug 22, 2019
A generic, spec-compliant, thorough implementation of the OAuth request-signing logic

OAuthLib - Python Framework for OAuth1 & OAuth2 *A generic, spec-compliant, thorough implementation of the OAuth request-signing logic for Python 3.5+

OAuthlib 2.5k Jan 02, 2023
Simple extension that provides Basic, Digest and Token HTTP authentication for Flask routes

Flask-HTTPAuth Simple extension that provides Basic and Digest HTTP authentication for Flask routes. Installation The easiest way to install this is t

Miguel Grinberg 1.1k Jan 05, 2023
Auth for use with FastAPI

FastAPI Auth Pluggable auth for use with FastAPI Supports OAuth2 Password Flow Uses JWT access and refresh tokens 100% mypy and test coverage Supports

David Montague 95 Jan 02, 2023
it's a Django application to register and authenticate users using phone number.

django-phone-auth It's a Django application to register and authenticate users using phone number. CustomUser model created using AbstractUser class.

MsudD 4 Nov 29, 2022
A Python package, that allows you to acquire your RecNet authorization bearer token with your account credentials!

RecNet-Login This is a Python package, that allows you to acquire your RecNet bearer token with your account credentials! Installation Done via git: p

Jesse 6 Aug 18, 2022
Foundation Auth Proxy is an abstraction on Foundations' authentication layer and is used to authenticate requests to Atlas's REST API.

foundations-auth-proxy Setup By default the server runs on http://0.0.0.0:5558. This can be changed via the arguments. Arguments: '-H' or '--host': ho

Dessa - Open Source 2 Jul 03, 2020
OpenStack Keystone auth plugin for HTTPie

httpie-keystone-auth OpenStack Keystone auth plugin for HTTPie. Installation $ pip install --upgrade httpie-keystone-auth You should now see keystone

Pavlo Shchelokovskyy 1 Oct 20, 2021
Django x Elasticsearch Templates

Django x Elasticsearch Requirements Python 3.7 Django = 3 Elasticsearch 7.15 Setup Elasticsearch Install via brew Install brew tap elastic/tap brew

Aji Pratama 0 May 22, 2022
Get inside your stronghold and make all your Django views default login_required

Stronghold Get inside your stronghold and make all your Django views default login_required Stronghold is a very small and easy to use django app that

Mike Grouchy 384 Nov 23, 2022
JSON Web Token Authentication support for Django REST Framework

REST framework JWT Auth JSON Web Token Authentication support for Django REST Framework Overview This package provides JSON Web Token Authentication s

Styria Digital Development 178 Jan 02, 2023
Skit-auth - Authorization for skit.ai's platform

skit-auth This is a simple authentication library for Skit's platform. Provides

Skit 3 Jan 08, 2022
Django-react-firebase-auth - A web app showcasing OAuth2.0 + OpenID Connect using Firebase, Django-Rest-Framework and React

Demo app to show Django Rest Framework working with Firebase for authentication

Teshank Raut 6 Oct 13, 2022
Social auth made simple

Python Social Auth Python Social Auth is an easy-to-setup social authentication/registration mechanism with support for several frameworks and auth pr

Matías Aguirre 2.8k Dec 24, 2022