NextAuth-inspired pluggable authentication for FastAPI.
FastAuth gives you a complete auth system — credentials, OAuth, passkeys (WebAuthn), magic links, email verification, password reset, RBAC, and JWT — without locking you into any particular database or ORM.
- Multiple providers — email/password, magic links, Google OAuth, GitHub OAuth, passkeys (WebAuthn)
- OAuth account linking — connect additional providers to an existing account while authenticated
- Pluggable adapters — SQLAlchemy (SQLite, PostgreSQL, MySQL) or bring your own
- JWT & database sessions — stateless tokens or server-side sessions
- Cookie delivery — HttpOnly, Secure, SameSite out of the box
- Email flows — verification, password reset, and magic links with customizable transports
- Custom email templates — drop Jinja2 templates into any directory; unoverridden templates fall back to built-ins
- RBAC — roles and fine-grained permissions on any route
- Event hooks — intercept sign-in/sign-up and modify JWT payloads
- RS256 / JWKS — rotate keys and expose a JWKS endpoint for microservices
- CLI — scaffold a project, check dependencies, generate secrets
pip install "sreekarnv-fastauth[standard]"| Extra | Includes |
|---|---|
standard |
FastAPI, JWT (joserfc), SQLAlchemy, Argon2 |
oauth |
httpx (Google, GitHub OAuth) |
webauthn |
py-webauthn (passkeys / FIDO2) |
email |
aiosmtplib, Jinja2 |
redis |
redis-py async |
postgresql |
asyncpg |
cli |
typer, rich |
all |
everything |
from contextlib import asynccontextmanager
from fastapi import Depends, FastAPI
from fastauth import FastAuth, FastAuthConfig
from fastauth.adapters.sqlalchemy import SQLAlchemyAdapter
from fastauth.api.deps import require_auth
from fastauth.providers.credentials import CredentialsProvider
adapter = SQLAlchemyAdapter(engine_url="sqlite+aiosqlite:///./auth.db")
auth = FastAuth(FastAuthConfig(
secret="change-me", # fastauth generate-secret
providers=[CredentialsProvider()],
adapter=adapter.user,
token_adapter=adapter.token,
))
@asynccontextmanager
async def lifespan(app: FastAPI):
await adapter.create_tables()
yield
app = FastAPI(lifespan=lifespan)
auth.mount(app) # registers /auth/register, /auth/login, /auth/logout, …
@app.get("/dashboard")
async def dashboard(user=Depends(require_auth)):
return {"hello": user["email"]}uvicorn main:app --reloadPasswordless sign-in with a one-time link sent to the user's email. No password required — unknown emails are auto-registered on first use.
from fastauth.providers.magic_links import MagicLinksProvider
from fastauth.email_transports.smtp import SMTPTransport
auth = FastAuth(FastAuthConfig(
...
providers=[MagicLinksProvider()],
token_adapter=adapter.token,
email_transport=SMTPTransport(...),
base_url="https://your-app.com",
))pip install "sreekarnv-fastauth[standard,email]"See the Magic Links guide and example app.
Add Touch ID, Face ID, and Windows Hello sign-in with one extra import:
from fastauth.providers.passkey import PasskeyProvider
from fastauth.session_backends.memory import MemorySessionBackend
auth = FastAuth(FastAuthConfig(
...
providers=[
CredentialsProvider(),
PasskeyProvider(rp_id="example.com", rp_name="My App", origin="https://example.com"),
],
passkey_adapter=adapter.passkey,
passkey_state_store=MemorySessionBackend(),
))pip install "sreekarnv-fastauth[standard,webauthn]"See the Passkeys guide and example app.
Authenticated users can connect additional OAuth providers to their existing account — no new sign-in flow required.
# 1. Get the authorization URL (requires Bearer token)
GET /auth/oauth/google/link?redirect_uri=https://your-app.com/callback
# → {"url": "https://accounts.google.com/o/oauth2/auth?..."}
# 2. After the provider redirects back, the callback completes the link
GET /auth/oauth/google/link/callback?code=...&state=...
# → {"message": "Google account linked successfully"}
# 3. List all linked providers
GET /auth/oauth/accountsRequires oauth_state_store and oauth_adapter in FastAuthConfig. Attempting to link an already-linked provider account returns 400.
Drop Jinja2 templates into any directory to override FastAuth's built-in emails. Only the files you provide are replaced — everything else falls back to the defaults automatically.
from pathlib import Path
auth = FastAuth(FastAuthConfig(
...
email_template_dir=Path("my_templates/"),
))| Template file | Sent when | Variables |
|---|---|---|
welcome.jinja2 |
User registers | name |
verification.jinja2 |
Email verification | name, url, expires_in_minutes |
password_reset.jinja2 |
Password reset | name, url, expires_in_minutes |
email_change.jinja2 |
Email change | name, new_email, url, expires_in_minutes |
magic_link_login.jinja2 |
Magic link sign-in | name, url |
See the example app.
Full documentation at sreekarnv.github.io/fastauth
- Installation
- Quick Start
- Configuration
- How it Works
- Magic Links
- Passkeys (WebAuthn)
- Guides
- API Reference
MIT License - see LICENSE for details.