Authentication for FastAPI. Secure defaults. Simple APIs. Powerful customization.
Building authentication from scratch is slow and error-prone. AllSafe Fast gives you a complete, secure, async-first auth system so you can ship features instead of reinventing login flows.
Argon2id password hashing, SHA-256 hashed token storage, refresh-token rotation with theft detection, CSRF protection, enumeration prevention, and production configuration guards — all enabled out of the box.
Three lines to attach auth to your app. Protect any route with auth.user(). Require roles, permissions, or verified emails with a single keyword argument. No boilerplate.
Every database, Redis, and HTTP operation is async. The framework never blocks the event loop. Storage protocols, providers, and session management are all async end to end.
Five built-in providers — Password, OAuth 2.0, OIDC, Magic Link, Email OTP. Every provider implements the same AuthProvider protocol. Add your own without touching core logic.
JWT verification happens in memory on every request — no database query on the hot path. Rate limiting, secure cookies, and production guards that refuse insecure configurations at startup.
14 lifecycle hooks, a full plugin system, protocol-based storage, and a CLI for setup and diagnostics. Extend AllSafe Fast with 2FA, organizations, API keys, or anything else you need.
From zero to a protected FastAPI endpoint in five steps:
.env file with allsafe init.
Auth() instance and attach it to your FastAPI app. Include the auth router.
user=auth.user() as a dependency to any route. Require roles or permissions with keyword args.
ALLSAFE_ENV=production and let the production guards verify your configuration is safe.
from fastapi import FastAPI
from allsafe_fast import Auth
app = FastAPI()
auth = Auth()
auth.attach(app)
app.include_router(auth.router, prefix="/auth")
# Any authenticated user
@app.get("/me")
async def me(user=auth.user()):
return {"id": str(user.id), "email": user.email}
# Require a specific role
@app.get("/admin")
async def admin(user=auth.user(role="admin")):
return {"message": f"Hello admin {user.email}"}
# Require a specific permission
@app.get("/reports/export")
async def export(user=auth.user(permission="reports:export")):
return {"message": "Exporting reports..."}
Password, OAuth 2.0 (with PKCE), OIDC (with JWKS discovery), Magic Link, and Email OTP — all built in and ready to configure.
Short-lived access tokens (15 min) and long-lived refresh tokens (30 days) with automatic rotation and theft detection.
Modern memory-hard password hashing with configurable time, memory, and parallelism parameters. Salts managed for you.
Declarative route protection. Check a single role, any of several roles, a single permission, or all of a set of permissions.
JWT verification is pure computation — no database or Redis query on every request. Your protected routes stay fast under load.
Four storage protocols with in-memory and async SQLAlchemy implementations. Swap backends without touching core logic.
Run custom logic on user creation, sign-in, session creation, password reset, email verification, and account linking.
Extend AllSafe Fast with custom routes, database tables, hooks, and schemas. Implement the AllSafePlugin protocol.
allsafe init, allsafe secret, allsafe db generate, allsafe db migrate, and allsafe doctor.
Cookie-based auth requires the X-AllSafe-CSRF header on every request. Bearer-token auth is immune by design.
Sliding-window rate limiter with a Redis backend for production or an in-memory backend for development.
The framework refuses to start in production with a default secret key or insecure cookies. Fail fast, fail safe.
Follow the quick start guide to install AllSafe Fast, configure it, and protect your first route in minutes.