A modular, Pydantic-native, async-only authentication library for FastAPI.
Project description
fastauth
A modular, Pydantic-native, async-only authentication library for FastAPI.
pip install fastauth-py
from fastapi import FastAPI
from pydantic import SecretStr
from fastauth import FastAuth, FastAuthConfig
from fastauth.storage.memory import InMemoryAdapter
app_secret = "replace-me-with-a-secret-from-your-application-config"
config = FastAuthConfig(secret_key=SecretStr(app_secret))
auth = FastAuth(config, adapter=InMemoryAdapter())
app = FastAPI(lifespan=auth.lifespan)
auth.install(app)
That's it. You now have /auth/sign-up/email, /auth/sign-in/email,
/auth/sign-out, /auth/get-session, /auth/verify-email,
/auth/forgot-password, /auth/reset-password, /auth/change-password,
/auth/set-password, /auth/verify-password, /auth/user,
/auth/delete-account, /auth/delete-account/request,
/auth/delete-account/confirm,
/auth/change-email/{request,confirm}, /auth/sessions (list / revoke /
revoke-others), /auth/refresh, and /auth/health wired into your FastAPI
application. Rate-limiting, account-lockout, and refresh tokens are part of
the router. CSRF and security headers are ASGI middleware installed by
auth.install(app). If you use auth.as_asgi() instead, fastauth returns a
standalone app with the same routes and middleware already installed.
Why fastauth
Built deliberately for the modern Python web stack — FastAPI + Pydantic v2 + async-only + MongoDB or Postgres persistence:
- Pydantic v2 everywhere. Every domain model, every request body, every
response is a
BaseModel. Nodataclass/NamedTuple/TypedDictsmuggled in. Four documented carve-outs for plain dicts (OpenAPI schema, JWK, JWT payload, HTTP headers); everything else is typed. - Async-only. No sync wrappers, no thread-pool shims. Your event loop doesn't get hijacked.
- Strict-typed.
pyright --strictpasses with 0 errors, 0 warnings.py.typedmarker ships with the wheel — your IDE and your CI get full type information. - Source-agnostic config.
FastAuthConfigis a plainBaseModel. The framework never reads process-level configuration. You build config from your application settings object, vault client, parameter store, or test fixture and pass it in explicitly. - Plugins as first-class extension points. Six built-in plugins
(
ApiKeyPlugin,JwtPlugin,EmailOtpPlugin,AuditLogsPlugin,OpenApiPlugin,TestUtilsPlugin) — each contributes endpoints, event handlers, lifecycle hooks, and rate-limit policies through a tightPluginABC. Write your own for OAuth providers, webhooks, custom MFA — whatever your app needs. - Capability-based storage protocols.
DatabaseAdaptercovers the core auth flows. Optional surfaces (ApiKeyStore,JwksKeyStore,AuditLogStore,RateLimitStore) are only required when you enable the matching plugin or database-backed feature. - Pure events. A single typed
EventBuscarries 19 concreteAuthEventsubclasses (UserSignedUp,UserEmailVerified,PasswordChanged,AccountLockedOut, …). Subscribe and react — send emails, ping Slack, write audit rows, whatever.
What's in the box
Auth flows
- Sign-up / sign-in / sign-out by email or username
- Email verification with anti-enumeration
- Password reset with anti-enumeration and session-wide revoke
- Authenticated change-password (keeps current session, revokes others)
- Authenticated profile update, set-password, verify-password, and account deletion with password or email-token verification
- Authenticated change-email with re-verification
- Refresh tokens with one-time-use rotation and family-revocation on reuse (OAuth 2.1-style theft detection)
- Multi-session management: list, revoke one, revoke-all-except-current
Sessions
- Database-backed sessions (revocable, IP/UA bound) or JWT sessions (stateless, JWKS-signed). One config flag flips between them.
- JWKS with auto-generated keys, AES-GCM at-rest encryption with master-key
rotation support, and an opt-in
set-auth-jwtresponse header that attaches a JWT to every authenticated response. - Local key signing or plug in your own
KmsSigner(HSM, AWS KMS, GCP KMS, …) via a tiny Protocol. - JWT/JWKS crypto has not been independently audited. For high-stakes production deployments, use an external KMS/HSM signer and run your own security review before relying on local private-key storage.
Security
- Argon2id password hashing (configurable cost).
- Account lockout — HTTP 423 +
Retry-Afterafter 5 failed sign-ins in 15 min. - CSRF middleware — Origin/Referer validation on state-changing methods, bearer-only requests are exempt.
- Rate limiting with /64 IPv6-subnet bucketing, per-(IP, path) windowing, pluggable storage (memory, MongoDB, Postgres).
- Security headers — HSTS,
X-Frame-Options,X-Content-Type-Options,Referrer-Policyon by default; opt-inPermissions-Policyand CSP.
Plugins (each optional)
- ApiKeyPlugin — create/verify/list/update/delete API keys with optional refilling quotas and per-key rate limits.
- JwtPlugin —
/auth/tokento mint a JWT from a session,/auth/jwksfor the public key set. - EmailOtpPlugin — passwordless sign-in, email verification, password reset, and (optional) email change via 6-digit OTPs delivered to email. Hashed storage, per-OTP attempt cap, lockout-coupled.
- AuditLogsPlugin — auto-captures every
AuthEventinto a paginated audit-log collection. - OpenApiPlugin — Scalar UI at
/auth/reference, OpenAPI 3.1 schema at/auth/openapi.json. - TestUtilsPlugin — factories, login helpers, OTP capture for tests.
Developer experience
CurrentUser/CurrentSessionFastAPI dependencies with optional variants, bothDepends(...)andAnnotated[...]calling styles documented.- Explicit storage wiring — pass
InMemoryAdapter(),BeanieAdapter, orPostgresAdapteryourself. Fastauth never silently chooses persistence. auth.install(app)— install routes, CSRF, and security headers on your FastAPI app in one call.FastAuth.as_asgi()still returns a standalone app when you want fastauth mounted separately.- Typer CLI —
fastauth init --backend memory|mongo|postgres,fastauth migrate,fastauth generate-secret. - mkdocs-material docs + quickstart example app with its own test suite.
Installation
# Core (in-memory adapter only — useful for tests and local dev)
pip install fastauth-py
# MongoDB-backed production
pip install fastauth-py[beanie,jwt]
# Postgres-backed production
pip install fastauth-py[postgres,jwt]
# All implemented optional extras
pip install fastauth-py[beanie,postgres,jwt,cli,docs]
Extras: beanie (MongoDB), postgres (SQLAlchemy async + asyncpg), jwt
(JOSE signing + crypto for at-rest JWK encryption), cli (Typer CLI),
docs (mkdocs-material toolchain).
Python 3.11+ required. FastAPI 0.115+, Pydantic 2.8+.
Protecting routes
from fastapi import Depends
from fastauth.domain.models import User
@app.get("/me")
async def me(user: User = Depends(auth.get_current_user)) -> User:
return user
Or with the Annotated style (FastAPI's idiom):
from typing import Annotated
from fastapi import Depends
from fastauth.domain.models import User
CurrentUser = Annotated[User, Depends(auth.get_current_user)]
@app.get("/me")
async def me(user: CurrentUser) -> User:
return user
Cookie auth and Authorization: Bearer … both work — fastauth handles either
transparently. Use auth.get_optional_current_user if anonymous requests
are allowed.
Configuration
FastAuthConfig is a plain pydantic.BaseModel. Every field has a sensible
default; pass only what you want to override:
from fastauth import FastAuthConfig
from fastauth.config import (
AppConfig, CookieConfig, CsrfConfig,
LockoutConfig, RefreshTokenConfig, SecurityHeadersConfig,
)
config = FastAuthConfig(
secret_key=SecretStr("…"),
app=AppConfig(name="My App", base_url="https://myapp.com"),
cookie=CookieConfig(secure=True, same_site="strict"),
csrf=CsrfConfig(trusted_origins=["https://myapp.com"]),
lockout=LockoutConfig(max_failures=10, window_seconds=300),
refresh_token=RefreshTokenConfig(max_age_seconds=14 * 24 * 3600),
security_headers=SecurityHeadersConfig(
content_security_policy="default-src 'self'",
),
)
16 sub-configs cover app, session, cookie, password, email,
email_verification, password_reset, email_change, delete_account,
rate_limit, csrf, lockout, refresh_token, security_headers,
database, advanced.
See docs/concepts/config.md for the full reference.
Documentation
Full docs site: mkdocs serve from a checkout.
- Quickstart
- Config · Sessions · Plugins · Adapters · CSRF · Events · Hooks
- Email verification guide · Password reset guide · User management guide · KMS signing guide
Project layout
fastauth/
├── config.py / exceptions.py # top-level
├── domain/ # pure data: enums, models, events
├── security/ # auth primitives: passwords, tokens, sessions, jwt,
│ # refresh_tokens, lockout, rate_limit
├── storage/ # Core/optional adapter protocols + InMemory/Beanie/Postgres backends
├── messaging/ # email + Jinja2 templates
├── flows/ # sign-up, sign-in, verification, refresh, …
├── plugins/ # api_key, jwt, audit_logs, openapi, test_utils
├── runtime/ # FastAuth, AuthContext, AuthApi, EventBus, hooks
├── web/ # FastAPI integration + CSRF + security headers
└── cli/ # Typer CLI
Status
v0.1.0 — first release. Coverage spans unit tests, adapter-contract tests,
integration flows, CLI behavior, and the quickstart example. pyright --strict
is clean. See CHANGELOG.md for the detailed feature list.
Roadmap (v0.2+):
- OAuth providers (Google → GitHub → Apple → Microsoft)
- 2FA / TOTP
- Webhooks
- HIBP password breach check
- Audit-log enrichment (geo-IP, UA parsing)
Contributing
See CONTRIBUTING.md for the project-wide rules (no leading-underscore names, async-only, Pydantic-everywhere, …). Quick development loop:
uv sync --all-extras
uv run ruff check
uv run pyright
uv run pytest
uv run mkdocs serve
License
MIT — see LICENSE.
Project details
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 fastauth_py-0.2.2.tar.gz.
File metadata
- Download URL: fastauth_py-0.2.2.tar.gz
- Upload date:
- Size: 82.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
36c3dd6872d4abe39862a5c6d0c7352a8e59e15f8a38cf88c69394565c1c3424
|
|
| MD5 |
501a4d3273255f2469ab0057bad535e5
|
|
| BLAKE2b-256 |
d9b633d2af38ecd392d45a071c01cf05192af6f2b192937ffc70eadcf687d92d
|
Provenance
The following attestation bundles were made for fastauth_py-0.2.2.tar.gz:
Publisher:
publish.yml on bhargavandhe/fastauth
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastauth_py-0.2.2.tar.gz -
Subject digest:
36c3dd6872d4abe39862a5c6d0c7352a8e59e15f8a38cf88c69394565c1c3424 - Sigstore transparency entry: 1970813789
- Sigstore integration time:
-
Permalink:
bhargavandhe/fastauth@941296152f2cf3914b19e539cd6c7a8953b0b5d5 -
Branch / Tag:
refs/tags/v0.2.2 - Owner: https://github.com/bhargavandhe
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@941296152f2cf3914b19e539cd6c7a8953b0b5d5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file fastauth_py-0.2.2-py3-none-any.whl.
File metadata
- Download URL: fastauth_py-0.2.2-py3-none-any.whl
- Upload date:
- Size: 120.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7345505eb129499a6fdf6ab09ff2a2a36d0f534e1a5ca0cd1b1468e172246354
|
|
| MD5 |
edc167daa33e780cff23498d2b25f88e
|
|
| BLAKE2b-256 |
adc89571f1c2c4ed2a31f1aa6587174cddafa98905bd57907de631984c0c358d
|
Provenance
The following attestation bundles were made for fastauth_py-0.2.2-py3-none-any.whl:
Publisher:
publish.yml on bhargavandhe/fastauth
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastauth_py-0.2.2-py3-none-any.whl -
Subject digest:
7345505eb129499a6fdf6ab09ff2a2a36d0f534e1a5ca0cd1b1468e172246354 - Sigstore transparency entry: 1970813896
- Sigstore integration time:
-
Permalink:
bhargavandhe/fastauth@941296152f2cf3914b19e539cd6c7a8953b0b5d5 -
Branch / Tag:
refs/tags/v0.2.2 - Owner: https://github.com/bhargavandhe
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@941296152f2cf3914b19e539cd6c7a8953b0b5d5 -
Trigger Event:
push
-
Statement type: