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.
💖 Support My Work
If you find my free content and projects helpful, consider supporting me to enable more learning resources for the community. Your contributions will go towards creating new content and maintaining existing projects.
Ways to Support
You can contribute by making a donation through PayPal:
You can contribute by making a donation through Buy Me a Coffee:
Your generosity is greatly appreciated!
Why Support?
By supporting this project, you help ensure the continued availability of free educational content and the development of new projects. Your contribution makes a meaningful impact on the community of learners.
Thank you for your support!
📄 License
This project is licensed under the MIT License — see the LICENSE file for details.
Metadata
Release files for flask-advanced-auth 0.1.2
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.2.tar.gz | 27.6 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| flask_advanced_auth-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 52.4 kB
Release files / flask_advanced_auth-0.1.2.tar.gz
| Download URL | flask_advanced_auth-0.1.2.tar.gz |
|---|---|
| Size | 27.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8bfa89cc022f02395ff0006113611e8fc89d8fe48c88aea896042f71e9a34676
|
|
BLAKE2b-256 checksum How to use checksums |
48454c1da00be0d2b14838af9c917608b8f682442b16f19afb7c1de91ec308a4
|
| 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.2-py3-none-any.whl
| Download URL | flask_advanced_auth-0.1.2-py3-none-any.whl |
|---|---|
| Size | 24.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
842e9f96478ab95fd7af02e5d04e8cd6c77011f3d7c2508a5d7c70301898f6ee
|
|
BLAKE2b-256 checksum How to use checksums |
7c61fb3bdfac78117d7ca02e14015a1c520ec621eb71343181d2b3d4fe08130f
|
| 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.2
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.