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.


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

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

Built distribution (wheel)

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

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

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