Skip to main content

flask-advanced-auth

PyPI version Python versions License: MIT Tests Coverage

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 into request.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:

Donate

You can contribute by making a donation through Buy Me a Coffee:

"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)

Source distribution for flask-advanced-auth 0.1.2
File Size Uploaded Provenance
flask_advanced_auth-0.1.2.tar.gz 27.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for flask-advanced-auth 0.1.2
File Interpreter ABI Platform
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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page