flask-advanced-auth
flask-advanced-auth is a production-grade, highly configurable JWT authentication extension for Flask and Flask-SQLAlchemy. It provides multi-rule support (different token lifetimes, secrets, and models for users vs. admins), built-in database token tracking, automatic token revocation (blacklisting), and clean route decorators.
✨ Features
- 🔑 Multi-Rule Authentication: Define distinct rules for different user tiers (e.g.
users,managers,api_clients) with independent secrets, algorithms, and lifetimes. - 🛡️ Easy Route Protection: Clean
@authenticate(auth_classes=[AuthenticateJWT])decorator with customizable 401 response and model injection intorequest.instance. - 🔄 Access & Refresh Tokens: Native support for short-lived access tokens and long-lived refresh tokens with convenient
refresh_access_token()helper. - 🚫 Token Revocation (Blacklisting): Built-in revocation mechanism with database persistence and
logout()helper. - 📊 Token Tracking: Track issued tokens in the database to detect anomalies, enforce single-session limits, or audit activity.
- 🔌 Multiple Extraction Strategies: Extract tokens from
Authorization: Bearer <token>headers, HTTP cookies, or URL query parameters. - ⚡ Pydantic Validation: Strict configuration schema validation powered by Pydantic V2 with flexible aliases.
- 🧪 Thoroughly Tested: 100% test pass rate with ≥ 88% test coverage.
📦 Installation
pip install flask-advanced-auth
Or install with development dependencies:
pip install flask-advanced-auth[dev]
🚀 Quick Start (5 Minutes)
1. Configure Rules & Bootstrap
from datetime import timedelta
from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy
from flask_advanced_auth import (
initialize_jwt_authentication,
authenticate,
AuthenticateJWT,
TokenFactory,
refresh_access_token,
logout,
)
app = Flask(__name__)
app.config["SECRET_KEY"] = "your-app-secret"
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
db = SQLAlchemy(app)
# Define your JWT rules
JWT_RULES = {
"default": {
"description": "Standard user access token",
"secret_key": "your-jwt-secret-key",
"algorithm": "HS256",
"access_token_lifetime": timedelta(minutes=15),
"refresh_token_lifetime": timedelta(days=7),
"token_header": "Bearer ",
}
}
# Initialize flask-advanced-auth
initialize_jwt_authentication(
database_path="app.db",
rules=JWT_RULES,
)
2. Issue Tokens on Login
@app.route("/api/login", methods=["POST"])
def login():
username = request.json.get("username")
factory = TokenFactory()
access_token = factory.generate_token(
rule_name="default",
extra_payload={"sub": username},
)
refresh_token = factory.generate_refresh_token(
rule_name="default",
extra_payload={"sub": username},
)
return jsonify({
"access_token": access_token,
"refresh_token": refresh_token,
})
3. Protect Routes
@app.route("/api/dashboard")
@authenticate(auth_classes=[AuthenticateJWT], rule_name="default")
def dashboard():
return jsonify({"message": "Welcome to your protected dashboard!"})
4. Refresh Tokens & Logout
@app.route("/api/refresh", methods=["POST"])
def refresh():
token = request.json.get("refresh_token")
new_access_token = refresh_access_token(token, rule_name="default")
return jsonify({"access_token": new_access_token})
@app.route("/api/logout", methods=["POST"])
def user_logout():
token = request.headers.get("Authorization", "").replace("Bearer ", "")
logout(token, rule_name="default")
return jsonify({"message": "Token revoked successfully."})
⚙️ Configuration Reference
Rules are passed as a dictionary where each key represents a rule name (e.g. "default", "admin"):
| Field | Type | Default | Description |
|---|---|---|---|
description |
str |
Required | Description of what this token rule is used for. |
secret_key |
str |
Required | Secret signing key for encoding and decoding tokens. |
algorithm |
str |
Required | JWT signing algorithm (e.g. 'HS256', 'RS256'). |
access_token_lifetime |
timedelta |
Required | Expiry duration for access tokens. |
refresh_token_lifetime |
timedelta |
None |
Expiry duration for refresh tokens. |
token_header |
str |
'Bearer ' |
Expected header prefix in Authorization header. |
table |
bool |
False |
Whether to link tokens to a database entity. |
table_path |
str |
None |
Dotted import path to model class (e.g. 'myapp.models.User'). |
track_created |
bool |
False |
Persist issued tokens to the database. |
track_created_table_path |
str |
None |
Dotted import path to TrackModel class. |
track_created_allow_duplicates |
bool |
True |
Allow multiple active tokens for the same user. |
blacklisted |
bool |
False |
Enable token blacklist checks on verification. |
blacklisted_table_path |
str |
None |
Dotted import path to BlackListModel class. |
🧩 Authentication Strategies
You can choose how tokens are extracted by passing different authentication classes to @authenticate:
from flask_advanced_auth import (
authenticate,
HeaderAuthentication, # Reads Authorization: Bearer <token>
CookieAuthentication, # Reads token from HTTP cookies
QueryParamAuthentication, # Reads ?token=<token>
)
# 1. From Authorization header
@app.route("/api/v1/data")
@authenticate(auth_classes=[HeaderAuthentication])
def api_data():
return {"status": "ok"}
# 2. From Cookie
@app.route("/web/profile")
@authenticate(auth_classes=[CookieAuthentication])
def web_profile():
return {"status": "ok"}
# 3. From URL parameter (e.g., SSE or WebSocket connection handshake)
@app.route("/stream")
@authenticate(auth_classes=[QueryParamAuthentication])
def stream():
return {"status": "connected"}
🗄️ Database Model Mixins
When enabling track_created or blacklisted, use our ready-to-use SQLAlchemy model mixins:
from flask_advanced_auth.models import AbstractTrackModelMixin, AbstractBlackListModelMixin
from myapp.database import db
class TrackedToken(db.Model, AbstractTrackModelMixin):
__tablename__ = "tracked_tokens"
class BlacklistedToken(db.Model, AbstractBlackListModelMixin):
__tablename__ = "blacklisted_tokens"
🧪 Running Tests
# Run tests with coverage
pytest -v
# Run single test module
pytest tests/test_decorators.py -v
🤝 Contributing
Contributions are welcome! Please check out CONTRIBUTING.md for setup instructions and guidelines.
📄 License
This project is licensed under the MIT License — see the LICENSE file for details.
Metadata
Release files for flask-advanced-auth 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| flask_advanced_auth-0.1.0.tar.gz | 27.2 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| flask_advanced_auth-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 51.7 kB
Release files / flask_advanced_auth-0.1.0.tar.gz
| Download URL | flask_advanced_auth-0.1.0.tar.gz |
|---|---|
| Size | 27.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
791eafba3cfe9dfe2b77c4db8bcfab5aa1fb3609eabe3119de0d3894b6b1a46d
|
|
BLAKE2b-256 checksum How to use checksums |
7c846c9e9961e68db3a96428f97e1bb1ec7f13bbf8bd8131e35e3461332dcc11
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.8.15
|
Release files / flask_advanced_auth-0.1.0-py3-none-any.whl
| Download URL | flask_advanced_auth-0.1.0-py3-none-any.whl |
|---|---|
| Size | 24.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4e5562018cfe165ab4ac15ad88fd900d6745b3b35c825b62f7e9049e75ed8636
|
|
BLAKE2b-256 checksum How to use checksums |
d50a0673361c4126596bffc21894d837d155ff0129e037ce53c73963b56a861c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.8.15
|
Security for flask-advanced-auth 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.