A reusable, database-backed authentication, user management, and audit logs plugin for FastAPI with a built-in admin dashboard.
Project description
AuthKit FastAPI
A highly secure, reusable, database-backed authentication, user management, and audit logging plugin for FastAPI. Exposes standard JSON API endpoints, secures routes via role-based dependency injections, and renders a stunning out-of-the-box HTML admin dashboard.
Key Features
- Dual-Token JWT Security: Uses short-lived Access JWTs and long-lived Refresh JWTs. Checked in HTTP-only cookies first (highly secure for web applications) with Bearer Header fallback (for APIs and mobile applications).
- Database Session Revocation: Stores active refresh tokens securely (SHA-256 hashed) in the database. Allows users to sign out of single devices or revoke all sessions across all devices.
- Built-in Glassmorphic Admin Dashboard: Serves a premium dark-themed visual user administration panel. Admin users can activate/deactivate user accounts, change roles, inspect and search system audit logs, and revoke active device sessions.
- Hybrid Audit Trail Logging: Automatically records all security events (successful/failed logins, registrations, password resets) and exposes a helper function for host applications to record custom actions.
- SQLite & Supabase (Postgres) Compatibility: Built-in safeguards including dynamic UUID-as-String columns, event listeners to enforce foreign keys on SQLite, and generic JSON structures.
- CLI Scaffolding Tool: Spin up a fully configured authentication architecture in any project in seconds using
authkit init.
Installation
Install the package directly into your virtual environment:
pip install fast-authkit
Or using uv:
uv add fast-authkit
Getting Started: Bootstrap in 3 Steps
Step 1: Initialize code scaffolding
Run the initializer command in the root of your new project:
authkit init
# or
uv run authkit init
This scaffolds a local auth/ module and pre-fills environment files:
project-root/
├── .env # Active configuration values (ignored in git)
├── .env.example # Configuration template
└── auth/ # Local Auth Module
├── __init__.py
├── setup.py # SQLAlchemy engine & AuthKit instantiation
├── models.py # Subclassable database tables
└── schemas.py # Extensible validation schemas
Step 2: Configure variables
Review the generated .env file. A strong random secret key is automatically generated for you:
AUTHKIT_SECRET_KEY=e83d8a9f23...
AUTHKIT_DATABASE_URL=sqlite+aiosqlite:///./authkit.db
AUTHKIT_COOKIE_SECURE=False
AUTHKIT_COOKIE_SAMESITE=lax
Note: For production (e.g. Supabase Postgres), change AUTHKIT_DATABASE_URL to postgresql+asyncpg://... and set AUTHKIT_COOKIE_SECURE=True.
Step 3: Mount in your FastAPI app
In your main FastAPI entry point (e.g. main.py), import the bootstrapped module and mount the routers:
from fastapi import FastAPI
from auth import auth_kit, init_db
app = FastAPI(title="My AI Application")
# Mount JSON endpoints (register, login, refresh, logout, profile)
app.include_router(auth_kit.router, prefix="/auth", tags=["Authentication"])
# Mount Visual HTML Admin Dashboard
app.include_router(auth_kit.admin_router, prefix="/admin", tags=["Admin Panel"])
@app.on_event("startup")
async def startup():
# Automatically creates SQLite tables if they do not exist
await init_db()
Run your server:
uvicorn main:app --reload
You can now access:
- Interactive Swagger API Docs:
http://127.0.0.1:8000/docs - Visual Admin Dashboard:
http://127.0.0.1:8000/admin(to log in, create a user and set their role to"admin"in the database).
Integrating with Existing Projects (Manual Setup)
If you already have an existing project with defined database models and configurations, you do not need to use authkit init. You can integrate the prebuilt routers and mixins directly.
Step 1: Mixin Auth Columns into Your SQLAlchemy Models
Import the SQLAlchemy base mixins and mix them into your existing models in your models.py file:
from sqlalchemy import Column, String
from database import Base # Your existing declarative base
from authkit_fastapi.models import BaseUserMixin, BaseRefreshTokenMixin, BaseAuditLogMixin
# 1. Mix fields into your existing User model
class User(BaseUserMixin, Base):
__tablename__ = "users"
# Your existing columns
full_name = Column(String(100), nullable=True)
# 2. Inherit RefreshToken and AuditLog models
class RefreshToken(BaseRefreshTokenMixin, Base):
__tablename__ = "refresh_tokens"
class AuditLog(BaseAuditLogMixin, Base):
__tablename__ = "audit_logs"
Step 2: Initialize AuthKit
Create your configuration and instantiate AuthKit passing your existing session maker and models:
from authkit_fastapi import AuthKit, AuthKitConfig
from database import async_session_maker # Your existing async session maker
from models import User, RefreshToken, AuditLog
config = AuthKitConfig(
secret_key="your-secure-secret-key",
cookie_secure=True, # Set to True in production (HTTPS)
)
auth_kit = AuthKit(
config=config,
db_session_maker=async_session_maker,
user_model=User,
refresh_token_model=RefreshToken,
audit_log_model=AuditLog
)
Step 3: Mount Routers in FastAPI
Mount the prebuilt JSON endpoints and the Admin Dashboard routers directly inside your application:
from fastapi import FastAPI
from setup_auth import auth_kit # Import the instance from Step 2
app = FastAPI()
# Mount all JSON APIs (/auth/login, /auth/register, /auth/logout, etc.)
app.include_router(auth_kit.router, prefix="/auth", tags=["Auth"])
# Mount HTML Admin dashboard (/admin, /admin/dashboard, etc.)
app.include_router(auth_kit.admin_router, prefix="/admin", tags=["Admin Dashboard"])
Usage Guide
Protecting Host Application Routes
Secure your own application endpoints using Depends along with AuthKit dependencies:
from fastapi import FastAPI, Depends
from auth import auth_kit
app = FastAPI()
# 1. Require any active authenticated user
@app.get("/profile")
def read_profile(user = Depends(auth_kit.current_active_user)):
return {"email": user.email, "role": user.role}
# 2. Restrict to Administrators only
@app.get("/system-settings")
def admin_settings(admin = Depends(auth_kit.current_admin)):
return {"message": "Welcome back admin", "admin_id": admin.id}
# 3. Dynamic role requirements
@app.get("/moderation-queue")
def moderation_queue(user = Depends(auth_kit.requires_role("moderator"))):
return {"status": "ok", "moderated_by": user.email}
# 4. Multi-role checks
@app.get("/editor-panel")
def editor_panel(user = Depends(auth_kit.requires_roles(["admin", "editor"]))):
return {"message": "Granted access to editor/admin panel"}
Extending Database Tables
If you need to add custom columns to the User table (e.g., full_name, organization_id), simply edit the generated auth/models.py file:
# auth/models.py
from sqlalchemy import String, mapped_column
from authkit_fastapi.models import Base, BaseUserMixin
class User(Base, BaseUserMixin):
__tablename__ = "users"
# Custom fields added here!
full_name: Mapped[str] = mapped_column(String(100), nullable=True)
organization_id: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
Don't forget to update your Pydantic schemas in auth/schemas.py to match:
# auth/schemas.py
from authkit_fastapi.schemas import UserCreate, UserRead
class CustomUserCreate(UserCreate):
full_name: Optional[str] = None
class CustomUserRead(UserRead):
full_name: Optional[str]
Writing Custom Audit Logs
Keep track of critical operations in your app by using the hybrid audit logger:
from fastapi import FastAPI, Depends, Request
from sqlalchemy.ext.asyncio import AsyncSession
from auth import auth_kit
app = FastAPI()
@app.post("/train-ai-model")
async def run_ai(
request: Request,
db: AsyncSession = Depends(auth_kit.get_db),
user = Depends(auth_kit.current_active_user)
):
# Perform operation...
# Audit log entry created automatically with user ID, IP address, and User-Agent
await auth_kit.log_action(
db=db,
action="trained_ai_model",
user_id=user.id,
details={"model_type": "Transformer", "epochs": 10},
request=request
)
return {"success": True}
Local Sandbox Verification
A pre-packaged sandbox app is provided in the repository for quick testing.
- Sync dependencies:
uv sync - Run the sandbox:
uv run python examples/main.py - Log in as admin:
- Navigate to
http://127.0.0.1:8000/admin - Use email
admin@example.comand passwordadminpass123.
- Navigate to
Running Tests
To run the automated pytest test suite:
uv run pytest
AuthKit Architecture: Explained Simply
To help you understand how AuthKit secures your application under the hood, here is a detailed breakdown of the token lifecycle, database session tracking, and the password reset flow.
🎭 The Real-World Analogy: The Amusement Park
- Access Token (The Daily Ride Wristband): When you enter the amusement park, you get a colored paper wristband for the day. At every ride (endpoint), the ride operator (server middleware) just looks at your wristband to verify today's color. They don't check a computer database. It's extremely fast and easy. However, the wristband expires at the end of the day (short-lived Access Token) so you can't reuse it tomorrow.
- Refresh Token (The 7-Day Season Pass Card):
To get a new daily wristband tomorrow, you go to the ticket booth (the
/refreshendpoint) and scan your Season Pass Card (Refresh Token). The agent checks the database to verify your card is active and not blocked. If valid, they issue a new daily wristband (Access Token), print a new barcode on your card for security (Refresh Token Rotation), and extend your card's validity for another 7 days (rolling expiry). However, if you don't visit the park for 7 consecutive days, your card expires, and you must go to the main office (log in again with password) to get a new one. - Revocation (Blacklisting the Card): If you click "Logout" or an admin deactivates your account, your Season Pass Card's barcode is instantly blacklisted in the system database. The next time you try to scan it at the ticket booth, it is rejected immediately, even if the 7-day timer has not run out.
1. Token & Session Lifecycle (Login, Access, and Refresh)
This sequence diagram illustrates the steps when a user logs in, accesses a protected API statelessly, and requests new tokens when their access token expires:
Under the Hood:
- Login: On successful authentication, AuthKit generates two JWTs: an Access Token (short lifespan) and a Refresh Token (long lifespan containing a unique random ID called
jti). - Session Record: The
jtiis hashed (SHA-256) and saved in the databaseRefreshTokentable along with the user's IP address and User-Agent. - HTTP-Only Cookies: Both tokens are set in the user's browser using secure,
HttpOnly,SameSite=Laxcookies so JavaScript scripts cannot steal them. - Token Rotation: When the Access Token expires, the client calls
/auth/refresh. AuthKit inspects the Refresh Token, queries the database to verify thejtisession record is not expired or markedis_revoked = True. If valid, it revokes the old session and issues brand new Access and Refresh tokens to prevent token reuse attacks.
2. Single-Use Password Reset Flow
This sequence diagram explains how AuthKit sends a password reset link and guarantees it cannot be reused (is strictly single-use) without creating extra database state:
Under the Hood:
- Link Request: The user submits their email. AuthKit reads their current
hashed_passwordfrom the database. - Cryptographic Signature (
pwd_sec): It hashes a segment of the current password hash and places it inside the JWT payload aspwd_sec. The reset link is sent to the user's email. - Submission & Verification: When the user opens the link and submits a new password, the server decodes the token, fetches the user, and compares the token's
pwd_secagainst the user's current database password hash. - Immediate Invalidation: Once the password is reset, the user's password hash in the database is updated. If the user clicks the reset link in the email again, the token's
pwd_secwill no longer match the user's new password hash, causing the validation to fail immediately. - Session Cleanup: Updating the password automatically revokes all other active device sessions (sets
is_revoked = Truefor all of the user's refresh tokens) for maximum account security.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fast_authkit-0.1.3.tar.gz.
File metadata
- Download URL: fast_authkit-0.1.3.tar.gz
- Upload date:
- Size: 2.0 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ff19c482e33c96b957aee94efd00096fcbff98759549a7ae8133cfa924c1908d
|
|
| MD5 |
d024145e5f637a369026f2dc8542f5fa
|
|
| BLAKE2b-256 |
ab3a77198af56630a27cb642dea49c33873e0b045e699051f1b43c6506214fbd
|
File details
Details for the file fast_authkit-0.1.3-py3-none-any.whl.
File metadata
- Download URL: fast_authkit-0.1.3-py3-none-any.whl
- Upload date:
- Size: 40.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dd45566aa7062814e3ee86db429595dfe264babce59ca5877181fc707e6f45ff
|
|
| MD5 |
d02f69cf30bfc767519f543fd6356ff4
|
|
| BLAKE2b-256 |
c2e8e6f1abc52c7dba588d29cafb0cbcc40fa07cd49a6abc536e571d241c9d95
|