CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-flask-httpauth

Simple extension that provides Basic and Digest HTTP authentication for Flask routes

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

multi-auth.mddocs/

Multi-Authentication

Combines multiple authentication methods into a single handler, automatically selecting the appropriate authentication method based on request headers. MultiAuth enables flexible endpoint protection with fallback authentication schemes.

Capabilities

MultiAuth Class

Creates a multi-authentication handler that combines different authentication methods.

class MultiAuth:
    def __init__(self, main_auth, *args):
        """
        Initialize multi-authentication handler.
        
        Parameters:
        - main_auth: Primary authentication method (used as fallback)
        - *args: Additional authentication methods to support
        
        Usage:
        multi_auth = MultiAuth(basic_auth, token_auth, digest_auth)
        """

Route Protection

Protect Flask routes with automatic authentication method selection.

def login_required(self, f=None, role=None, optional=None):
    """
    Decorator to require authentication using any compatible method.
    
    Parameters:
    - f (function, optional): Flask route function to protect
    - role (str|list, optional): Required user role(s)
    - optional (bool, optional): Make authentication optional
    
    Returns:
    Decorated function or decorator
    
    Usage:
    @multi_auth.login_required
    def flexible_endpoint():
        return f"Hello {multi_auth.current_user()}"
    
    @multi_auth.login_required(role='admin')
    def admin_endpoint():
        return "Admin access via any auth method"
    """

User Information

Access current authenticated user information within protected routes.

def current_user(self):
    """
    Get current authenticated user from whichever auth method was used.
    
    Returns:
    User object from the authentication method that handled the request
    """

Usage Examples

Basic + Token Authentication

from flask import Flask
from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth, MultiAuth
from werkzeug.security import generate_password_hash, check_password_hash

app = Flask(__name__)

# Set up Basic authentication
basic_auth = HTTPBasicAuth()
users = {
    "john": generate_password_hash("hello"),
    "susan": generate_password_hash("bye")
}

@basic_auth.verify_password
def verify_password(username, password):
    if username in users and check_password_hash(users.get(username), password):
        return username

# Set up Token authentication  
token_auth = HTTPTokenAuth('Bearer')
tokens = {
    "secret-token-1": "john",
    "secret-token-2": "susan"
}

@token_auth.verify_token
def verify_token(token):
    return tokens.get(token)

# Combine authentication methods
multi_auth = MultiAuth(basic_auth, token_auth)

@app.route('/api/data')
@multi_auth.login_required
def get_data():
    return {
        "user": multi_auth.current_user(),
        "data": "Available via Basic auth or Bearer token"
    }

# Usage examples:
# curl -u john:hello http://localhost:5000/api/data
# curl -H "Authorization: Bearer secret-token-1" http://localhost:5000/api/data

Three-Way Authentication

from flask import Flask
from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth, HTTPDigestAuth, MultiAuth

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret key'

# Set up Basic authentication
basic_auth = HTTPBasicAuth()

@basic_auth.verify_password
def verify_basic_password(username, password):
    users = {"john": "hello", "susan": "bye"}
    if username in users and users[username] == password:
        return username

# Set up Digest authentication
digest_auth = HTTPDigestAuth()

@digest_auth.get_password
def get_digest_password(username):
    users = {"john": "hello", "susan": "bye"}
    return users.get(username)

# Set up Token authentication
token_auth = HTTPTokenAuth('Bearer')

@token_auth.verify_token
def verify_token(token):
    tokens = {"token123": "john", "token456": "susan"}
    return tokens.get(token)

# Combine all three methods
multi_auth = MultiAuth(basic_auth, digest_auth, token_auth)

@app.route('/api/flexible')
@multi_auth.login_required
def flexible_endpoint():
    return {
        "message": f"Hello {multi_auth.current_user()}",
        "auth_method": "Any of: Basic, Digest, or Bearer token"
    }

Role-Based Multi-Auth

from flask import Flask
from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth, MultiAuth

app = Flask(__name__)

# Set up authentication methods
basic_auth = HTTPBasicAuth()
token_auth = HTTPTokenAuth('Bearer')

# User database with roles
users = {
    "john": {"password": "hello", "roles": ["user"]},
    "susan": {"password": "bye", "roles": ["user", "admin"]},
    "admin": {"password": "secret", "roles": ["admin"]}
}

tokens = {
    "user-token": {"user": "john", "roles": ["user"]},
    "admin-token": {"user": "susan", "roles": ["user", "admin"]}
}

@basic_auth.verify_password
def verify_password(username, password):
    if username in users and users[username]["password"] == password:
        return {"username": username, "roles": users[username]["roles"]}

@basic_auth.get_user_roles
def get_basic_user_roles(user):
    return user["roles"]

@token_auth.verify_token  
def verify_token(token):
    if token in tokens:
        return tokens[token]

@token_auth.get_user_roles
def get_token_user_roles(user):
    return user["roles"]

# Combine with role support
multi_auth = MultiAuth(basic_auth, token_auth)

@app.route('/api/user')
@multi_auth.login_required(role='user')
def user_endpoint():
    return {"message": f"User access: {multi_auth.current_user()}"}

@app.route('/api/admin')
@multi_auth.login_required(role='admin')
def admin_endpoint():
    return {"message": f"Admin access: {multi_auth.current_user()}"}

Custom Authentication Priority

from flask import Flask
from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth, MultiAuth

app = Flask(__name__)

# High-priority authentication (checked first)
api_key_auth = HTTPTokenAuth('ApiKey', header='X-API-Key')

@api_key_auth.verify_token
def verify_api_key(key):
    if key == "premium-api-key":
        return {"user": "premium_user", "tier": "premium"}

# Fallback authentication
basic_auth = HTTPBasicAuth()

@basic_auth.verify_password
def verify_password(username, password):
    if username == "regular" and password == "user":
        return {"user": "regular_user", "tier": "basic"}

# API key auth has priority over basic auth
multi_auth = MultiAuth(api_key_auth, basic_auth)

@app.route('/api/service')
@multi_auth.login_required
def service_endpoint():
    user = multi_auth.current_user()
    return {
        "user": user["user"],
        "tier": user["tier"],
        "message": "Service accessed with priority auth selection"
    }

# Usage:
# curl -H "X-API-Key: premium-api-key" http://localhost:5000/api/service (premium)
# curl -u regular:user http://localhost:5000/api/service (basic)

Authentication Method Selection

MultiAuth automatically selects the appropriate authentication method based on request headers:

  1. Header Inspection: Examines incoming request headers
  2. Compatibility Check: Tests each auth method's is_compatible_auth() method
  3. First Match: Uses the first compatible authentication method found
  4. Fallback: Uses main authentication method if no others match

The selection order follows the constructor parameter order: MultiAuth(first_priority, second_priority, ...).

Error Handling

MultiAuth delegates error handling to the selected authentication method:

  • 401 Unauthorized: No compatible authentication method found valid credentials
  • 403 Forbidden: Authentication succeeded but role authorization failed
  • Method-Specific Errors: Each auth method handles its own error responses
  • Automatic Header: WWW-Authenticate header from the selected auth method

The error response format depends on which authentication method processed the request.

Install with Tessl CLI

npx tessl i tessl/pypi-flask-httpauth

docs

basic-auth.md

digest-auth.md

index.md

multi-auth.md

roles.md

token-auth.md

tile.json