Skip to content

v0.5.3  ·  Python 3.11+  ·  FastAPI

FastAuth

NextAuth-inspired pluggable authentication for FastAPI.

Complete auth — credentials, OAuth, email verification, password reset, RBAC, and JWT in minutes. No ORM lock-in.

01

Multiple Providers

Email/password, Google OAuth, and GitHub OAuth out of the box.

02

Pluggable Adapters

SQLAlchemy (SQLite, PostgreSQL, MySQL) or bring your own.

03

JWT & Sessions

Stateless tokens or server-side sessions — your choice.

04

Cookie Delivery

HttpOnly, Secure, SameSite cookies with zero extra config.

05

Email Flows

Verification and password reset with pluggable transports.

06

RBAC

Roles and permissions enforced on any route via Depends.

07

Event Hooks

Intercept sign-in, sign-up, and mutate JWT payloads.

08

RS256 / JWKS

Rotate signing keys, expose a JWKS endpoint for microservices.

Install

pip install "sreekarnv-fastauth[standard]"
uv add "sreekarnv-fastauth[standard]"
poetry add "sreekarnv-fastauth[standard]"

The standard extra includes FastAPI, JWT (joserfc + cryptography), SQLAlchemy, and Argon2. See Installation for the full extras table.


Taste of the API

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, require_role
from fastauth.providers.credentials import CredentialsProvider

adapter = SQLAlchemyAdapter(engine_url="sqlite+aiosqlite:///./auth.db")

auth = FastAuth(FastAuthConfig(
    secret="change-me-in-production",   # 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"]}

@app.get("/admin")
async def admin(user=Depends(require_role("admin"))):
    return {"message": "welcome, admin"}

auth.mount(app) registers all auth endpoints automatically. Your routes just use Depends(require_auth).


Next steps