Skip to main content

Embeddable user registration, login, and account management for FastAPI apps. SQLite / Postgres / MongoDB.

Project description

regstack

CI Python 3.11+ FastAPI License: Apache 2.0

Production-grade user accounts for your FastAPI app — without the vendor lock-in, the second service to run, or the homegrown auth bugs.

pip install regstack, point it at SQLite (default), PostgreSQL, or MongoDB, and you have register / login / verify-email / reset-password / change-email / delete-account / optional SMS two-factor / admin endpoints / themable HTML pages — all behind a small Python API and one config file.

📚 Docs: https://regstack.readthedocs.io  ·  🧪 Try it: examples/sqlite  ·  🛡️ Security model: security guide


The problem regstack solves

Every web application that has users eventually needs the same dozen endpoints: register, log in, log out, verify email, reset a forgotten password, change password, change email, delete account, list users for the admin panel, lock out brute-force attackers, and ideally a second factor. Every one of those endpoints has a well-known way to get subtly wrong:

  • Password hashing. Use Argon2id, not MD5, SHA-1, bcrypt-without-pepper, or — somehow still common — plain text.
  • Token revocation. A JWT is signed and self-contained: the server can't "log it out" unless you build a revocation list. Forget this and a stolen token works until it expires.
  • Account enumeration. A login or password-reset endpoint that responds differently for "user exists" vs "user doesn't" lets an attacker harvest your customer list.
  • Bulk session invalidation. When a user changes their password because they think they were compromised, every existing token they hold should stop working immediately. Most homegrown JWT layers don't do this.
  • One-time tokens. Verification and password-reset tokens should be random, hashed at rest, single-use, and expire fast. Storing the raw token in the database is a "now your DB backup is also a credential dump" mistake.
  • Phone numbers. SMS codes need E.164-validated numbers, attempt limits, and an upstream provider. Wiring all of that yourself for a single feature is rarely worth it.

Doing all of these correctly, with tests, is two to four weeks of engineering for a competent team. Doing them once and embedding the result everywhere is what regstack is for.

What you get

✔ Email + password registration with email verification
✔ JWT login (RFC 7519) with per-token revoke AND bulk revoke
✔ Forgot / reset password — anti-enumeration: identical responses
✔ Change password (revokes old tokens) / change email (re-verify)
✔ Delete account
✔ Optional SMS two-factor (TOTP-style 6-digit codes over SMS)
✔ Server-side login lockout (HTTP 429 + Retry-After)
✔ Admin endpoints (list / disable / delete users, stats)
✔ Server-rendered HTML pages, theme with one CSS file
✔ Pluggable email (console / SMTP / Amazon SES) and SMS (Amazon SNS / Twilio)
✔ Argon2 password hashing, CSP-friendly templates
✔ Setup wizard (`regstack init`) and config validator (`regstack doctor`)
✔ Three storage backends: SQLite, PostgreSQL, MongoDB — chosen by URL

Every feature is opt-in. Mount only the JSON router for a headless backend; flip enable_ui_router to also get the bundled SSR pages. Skip the SMS extras and you don't pull twilio or aioboto3.

Why not just use…?

There are real alternatives. Here's why regstack might still be the right call.

Alternative Why you might pick it Why you might pick regstack instead
Auth0 / Clerk / WorkOS / Stytch (hosted SaaS) Zero ops. Polished UI. Enterprise SSO out of the box. Cost scales per-user. Your auth lives on someone else's servers. Your customer list is in their database. Vendor lock-in is real and migrations are painful.
Keycloak / Authentik / Authelia / Ory Kratos (self-hosted IAM) Full identity platform. SAML, OIDC, federation. A separate Java/Go service to run, monitor, back up, upgrade, and reason about. Heavyweight for "let users sign up". Schema lives outside your app.
fastapi-users Same language, same framework. Good registration / login primitives. Doesn't ship verification flows, anti-enumeration, bulk revoke, SMS MFA, admin endpoints, or themable pages — you build those. regstack is the longer tail.
Roll your own Total control. No dependency to learn. You re-solve every bullet from "The problem" above, including the ones you didn't know existed yet. Two to four engineering weeks, then forever to maintain.

regstack's bet is that for most FastAPI apps the right answer is embed a small Python library that owns the boring 80% correctly, and keep the user table in your own database — not "stand up a separate auth product" and not "write the boring 80% from scratch each time".

30-second start

git clone https://github.com/jdrumgoole/regstack && cd regstack
uv sync --extra dev

# Generate a JWT signing secret. SQLite is the default backend, no DB to install.
export REGSTACK_JWT_SECRET=$(python -c 'import secrets; print(secrets.token_urlsafe(64))')

uv run uvicorn examples.sqlite.main:app --reload

Then visit http://localhost:8000/account/login in your browser, or register from the command line:

curl -X POST http://localhost:8000/api/auth/register \
    -H 'content-type: application/json' \
    -d '{"email":"alice@example.com","password":"hunter2hunter2","full_name":"Alice"}'

The bundled example serves themed SSR pages at /account/*, prints verification / reset links and SMS codes to stdout (the console email/SMS backends), and shows how a host overrides regstack's default look by serving its own theme.css.

Want PostgreSQL or MongoDB instead? Set REGSTACK_DATABASE_URL to a postgresql+asyncpg://... or mongodb://... URL and install the matching extra (uv sync --extra postgres or uv sync --extra mongo). The schema is created on first boot.

Embed in your own app

from contextlib import asynccontextmanager

from fastapi import FastAPI

from regstack import RegStack, RegStackConfig


config = RegStackConfig.load()             # env vars + regstack.toml
regstack = RegStack(config=config)


@asynccontextmanager
async def lifespan(app: FastAPI):
    await regstack.install_schema()        # idempotent: runs migrations / creates indexes
    yield
    await regstack.aclose()


app = FastAPI(lifespan=lifespan)
app.include_router(regstack.router,    prefix=config.api_prefix)
app.include_router(regstack.ui_router, prefix=config.ui_prefix)   # optional
app.mount(config.static_prefix, regstack.static_files)            # optional

That is the whole integration. The rest of the surface area — extending the user model, registering hooks (user_registered, password_reset, …), supplying your own email service — is in the embedding guide.

Documentation

Page What's there
Quickstart Install, wizard, minimal embed
Configuration Every RegStackConfig field, env vars, TOML layout
Architecture Façade, backends, repos, hooks, lifecycle
Security model Threat model, JWT scheme, anti-enumeration, MFA
Embedding Custom backends, hooks, multi-tenant
Theming CSS variables, template overrides
CLI init, create-admin, doctor
API reference Public types, generated from source

The same docs are also browsable as Markdown in docs/.

Status

Alpha. Single-file SQLite is the default and runs with no infrastructure; PostgreSQL and MongoDB backends pass the same parametrized integration suite. Latest tagged release: v0.2.1. See the changelog for the per-release breakdown.

Contributing

Issues and pull requests welcome at https://github.com/jdrumgoole/regstack. Before opening a PR, please run the test suite and the linter — both should be green:

uv sync --extra dev
uv run python -m invoke test-all   # SQLite + Mongo + Postgres in parallel
uv run python -m invoke lint       # ruff + format check + mypy

invoke test-sqlite is the fast inner-loop variant that needs no database services. invoke test-all is what CI runs and what gates a release. Each pytest-xdist worker isolates its own database, so the full suite is safe to re-run while you iterate.

Security disclosures: see SECURITY.md.

License

Apache License 2.0 © 2026 Joe Drumgoole.

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

regstack-0.2.4.tar.gz (315.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

regstack-0.2.4-py3-none-any.whl (120.4 kB view details)

Uploaded Python 3

File details

Details for the file regstack-0.2.4.tar.gz.

File metadata

  • Download URL: regstack-0.2.4.tar.gz
  • Upload date:
  • Size: 315.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for regstack-0.2.4.tar.gz
Algorithm Hash digest
SHA256 bc8e1938e5b6ee12a31f179109356dcb4c21a7b981dd0ac39861679d25d9a200
MD5 13ca646dfdbec4d163c035227c81fb9b
BLAKE2b-256 ef3feab82d4aece2a02977d7af18c13520bf7695dddda72e05b89403b38e2044

See more details on using hashes here.

Provenance

The following attestation bundles were made for regstack-0.2.4.tar.gz:

Publisher: publish.yml on jdrumgoole/regstack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file regstack-0.2.4-py3-none-any.whl.

File metadata

  • Download URL: regstack-0.2.4-py3-none-any.whl
  • Upload date:
  • Size: 120.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for regstack-0.2.4-py3-none-any.whl
Algorithm Hash digest
SHA256 b4072e893690da8e1e01bce170b303cb857bf24d1c6ee17fc8045fae044e67f8
MD5 6bdd3aacc1f1cec8b16738b32dea6f00
BLAKE2b-256 44afb9af05c7266cfc7153fcf950e46d7ac484cffe53ab13a3b8296f33379d9b

See more details on using hashes here.

Provenance

The following attestation bundles were made for regstack-0.2.4-py3-none-any.whl:

Publisher: publish.yml on jdrumgoole/regstack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page