A Flask library for extending basic web authentication with multiple users and roles.
Have you ever designed a simple web app that you wanted a little more than basic authentication for, but didn't really have a need for full-blown sessions and a database for user management?
The goal offlask-basic-roles
is to bridge that gap and make it as simple as possible to add some role based security to a Flask based web service/REST API.
Install via pip:
pip install flask_basic_roles
Here's a very simple example building upon the Flask
quickstart guide that tries to demonstrate the functionality of this library.
from flask import Flask
from flask_basic_roles import BasicRoleAuth
app = Flask(__name__)
auth = BasicRoleAuth()
# Let's add some users.
auth.add_user(user='bob', password='secret123', roles='producer')
auth.add_user(user='alice', password='drowssap', roles=('producer','consumer'))
auth.add_user(user='bill', password='54321')
auth.add_user(user='steve', password='12345', roles='admin')
# Only producers and admins can post, while consumers can only get.
# Admins can also perform all other verbs.
@app.route("/task")
@auth.require(roles={
'POST': 'producer',
'GET': 'consumer',
'DELETE,POST,PATCH,PUT,GET': 'admin'
})
def tasks_endpoint(methods=(...)):
return "Here tasks get produced and consumed!"
# We can secure by user too. Steve can use any verb on this
# endpoint and everyone else is denied access.
@app.route("/task_status")
@auth.require(users='steve')
def task_status_endpoint(methods=(...)):
return "Here are the task statuses!"
# Alice, Bill and users with an 'admin' role can access this, while everyone
# else is denied on all verbs.
@app.route("/task_failures")
@auth.require(users=('alice', 'bill'), roles='admin')
def task_failures(methods=(...)):
return "Here are the task failures!"
# Everyone including unauthenticated users can view task results.
@app.route("/task_results")
def task_results(methods=(...)):
return "Here are the task results!"
if __name__ == "__main__":
app.run()
Yes! This is only supported in the API for demonstration and testing purposes. Users and their roles can (and should!) instead be specified in a file loaded via auth.load_from_file("file path here")
or auth = BasicRoleAuth(user_file="file path here")
.
This file defines each user one line at a time in the following format:
<user>:<password>:<role_1>,<role_2>,...<role_n>`
In the case of the above example, this would look like:
bob:secret123:producer
alice:drowssap:producer,consumer
bill:54321:
steve:12345:admin
This file can also be generated from a configured BasicRoleAuth
object via the auth.save_to_file("file path here")
function.
If a user fails to authenticate, then BasicRoleAuth.no_authentication
is executed to generate the response.
If a user authenticates (i.e. they provide a matching username and password), but their "account" has no authorization to perform the action (e.g. in the example above, bob
attempting to do DELETE
on /tasks
), then BasicRoleAuth.no_authorization
is executed to generate the response.
These methods can be overridden as follows:
def no_authentication():
return Response("My custom response here", 401)
auth = BasicRoleAuth()
auth.no_authentication = no_authentication
-
flask-basic-roles
is intended for small projects ideally without user registration (i.e. not a forum website or store) and for a small predefined number of users. If you are building something intended for a big audience, don't use this library! -
flask-basic-roles
does not provide transport level security. If you are building something for use outside of your LAN, secure it with HTTPS via a reverse proxy like NGINX. -
Passwords are in plain text. Support may be added later for digest access authentication. You should not use passwords you tend to use in a lot of different places with this library.