Simple extension that provides Basic and Digest HTTP authentication for Flask routes
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Role-based access control system that works across all Flask-HTTPAuth authentication methods. Supports simple roles, multiple roles per user, and complex role hierarchies with flexible authorization callbacks.
Register callback functions to define user roles for authorization.
def get_user_roles(self, f):
"""
Decorator to register user role retrieval callback.
Available on all authentication classes (HTTPAuth base class).
Parameters:
- f (function): Callback function(user) -> roles
Returns:
The decorated function
Usage:
@auth.get_user_roles
def get_user_roles(user):
# Return user roles as string, list, or set
return user_roles
"""Protect Flask routes with role requirements using the login_required decorator.
def login_required(self, f=None, role=None, optional=None):
"""
Decorator with role-based authorization support.
Available on all authentication classes.
Parameters:
- f (function, optional): Flask route function to protect
- role (str|list|tuple, optional): Required role(s)
- optional (bool, optional): Make authentication optional
Returns:
Decorated function or decorator
Role Matching:
- Single role: role='admin'
- Multiple roles (OR): role=['admin', 'moderator']
- Multiple roles (AND): role=[['read', 'write']]
Usage:
@auth.login_required(role='admin')
def admin_only():
return "Admin access"
@auth.login_required(role=['admin', 'moderator'])
def staff_access():
return "Admin or moderator access"
@auth.login_required(role=[['read', 'write']])
def full_permissions():
return "Must have both read AND write roles"
"""Internal authorization checking with support for complex role hierarchies.
def authorize(self, role, user, auth):
"""
Check if user is authorized for the required role(s).
Internal method called by login_required decorator.
Parameters:
- role (str|list|tuple|None): Required role(s)
- user: User object returned by authentication callback
- auth: Authentication object from request
Returns:
bool: True if authorized, False otherwise
Authorization Rules:
- None role: Always authorized (no role required)
- Single role: User must have exact role
- List roles: User must have at least one role (OR logic)
- Nested list: User must have all roles in inner list (AND logic)
"""from flask import Flask
from flask_httpauth import HTTPBasicAuth
app = Flask(__name__)
auth = HTTPBasicAuth()
# User database with roles
users = {
"john": {"password": "hello", "role": "user"},
"susan": {"password": "bye", "role": "admin"},
"bob": {"password": "secret", "role": "moderator"}
}
@auth.verify_password
def verify_password(username, password):
if username in users and users[username]["password"] == password:
return users[username]
@auth.get_user_roles
def get_user_roles(user):
return user["role"]
@app.route('/public')
def public():
return "Public access"
@app.route('/user')
@auth.login_required(role='user')
def user_area():
return f"User area: {auth.current_user()['role']}"
@app.route('/admin')
@auth.login_required(role='admin')
def admin_area():
return f"Admin area: {auth.current_user()['role']}"from flask import Flask
from flask_httpauth import HTTPBasicAuth
app = Flask(__name__)
auth = HTTPBasicAuth()
# Users with multiple roles
users = {
"john": {"password": "hello", "roles": ["user"]},
"susan": {"password": "bye", "roles": ["user", "admin"]},
"bob": {"password": "secret", "roles": ["user", "moderator"]},
"alice": {"password": "key", "roles": ["admin", "moderator"]}
}
@auth.verify_password
def verify_password(username, password):
if username in users and users[username]["password"] == password:
return users[username]
@auth.get_user_roles
def get_user_roles(user):
return user["roles"]
@app.route('/user')
@auth.login_required(role='user')
def user_area():
return "All authenticated users"
@app.route('/staff')
@auth.login_required(role=['admin', 'moderator'])
def staff_area():
return "Admin OR moderator access"
@app.route('/admin')
@auth.login_required(role='admin')
def admin_area():
return "Admin only"from flask import Flask
from flask_httpauth import HTTPBasicAuth
app = Flask(__name__)
auth = HTTPBasicAuth()
# Complex role system with permissions
users = {
"john": {
"password": "hello",
"roles": ["read", "user"]
},
"susan": {
"password": "bye",
"roles": ["read", "write", "admin", "user"]
},
"bob": {
"password": "secret",
"roles": ["read", "write", "user"]
}
}
@auth.verify_password
def verify_password(username, password):
if username in users and users[username]["password"] == password:
return users[username]
@auth.get_user_roles
def get_user_roles(user):
return user["roles"]
@app.route('/read')
@auth.login_required(role='read')
def read_data():
return "Read access granted"
@app.route('/write')
@auth.login_required(role='write')
def write_data():
return "Write access granted"
@app.route('/edit')
@auth.login_required(role=[['read', 'write']])
def edit_data():
return "Edit requires BOTH read AND write permissions"
@app.route('/admin')
@auth.login_required(role='admin')
def admin_panel():
return "Admin panel access"
@app.route('/superuser')
@auth.login_required(role=[['admin', 'write']])
def superuser_area():
return "Requires BOTH admin AND write permissions"from flask import Flask
from flask_httpauth import HTTPBasicAuth
app = Flask(__name__)
auth = HTTPBasicAuth()
# Simulate database lookup
class UserRoleManager:
def __init__(self):
# In real apps, this would be a database
self.users = {
"john": {"password": "hello", "id": 1},
"susan": {"password": "bye", "id": 2}
}
self.user_roles = {
1: ["user", "customer"],
2: ["user", "admin", "customer", "staff"]
}
def get_user(self, username, password):
user = self.users.get(username)
if user and user["password"] == password:
return user
return None
def get_roles(self, user_id):
return self.user_roles.get(user_id, [])
role_manager = UserRoleManager()
@auth.verify_password
def verify_password(username, password):
return role_manager.get_user(username, password)
@auth.get_user_roles
def get_user_roles(user):
return role_manager.get_roles(user["id"])
@app.route('/customer')
@auth.login_required(role='customer')
def customer_area():
return "Customer area"
@app.route('/staff')
@auth.login_required(role='staff')
def staff_area():
return "Staff area"from flask import Flask
from flask_httpauth import HTTPTokenAuth
import jwt
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret'
auth = HTTPTokenAuth('Bearer')
@auth.verify_token
def verify_token(token):
try:
# Decode JWT token with role information
data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
return {
"username": data["username"],
"roles": data.get("roles", [])
}
except jwt.InvalidTokenError:
return None
@auth.get_user_roles
def get_user_roles(user):
return user["roles"]
@app.route('/api/user')
@auth.login_required(role='user')
def user_api():
return {"message": f"User API: {auth.current_user()['username']}"}
@app.route('/api/admin')
@auth.login_required(role='admin')
def admin_api():
return {"message": f"Admin API: {auth.current_user()['username']}"}
# Token generation example
def generate_token(username, roles):
payload = {
"username": username,
"roles": roles,
"exp": datetime.utcnow() + timedelta(hours=1)
}
return jwt.encode(payload, app.config['SECRET_KEY'], algorithm='HS256')Flask-HTTPAuth supports flexible role matching:
@auth.login_required(role='admin')
# User must have exactly 'admin' role@auth.login_required(role=['admin', 'moderator'])
# User must have 'admin' OR 'moderator' role@auth.login_required(role=[['read', 'write']])
# User must have BOTH 'read' AND 'write' roles@auth.login_required(role=[['admin', 'write'], 'superuser'])
# User must have (admin AND write) OR superuserRole-based authorization generates appropriate HTTP status codes:
error_handler decoratorThe role authorization system integrates seamlessly with all Flask-HTTPAuth authentication methods and provides detailed error information for debugging role-based access issues.
Install with Tessl CLI
npx tessl i tessl/pypi-flask-httpauth