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 Argon2 (the PHC winner), 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. See OWASP WSTG-IDNT-04.
  • 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. The next tagged release is v0.2.0. See the changelog for the per-milestone 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.0.tar.gz (301.1 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.0-py3-none-any.whl (110.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: regstack-0.2.0.tar.gz
  • Upload date:
  • Size: 301.1 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.0.tar.gz
Algorithm Hash digest
SHA256 b66daba5cbc9f355fa617cf0e97da054cc45afdb1216bd4532e2ade7456a67a7
MD5 421ee25d6dfc52da7211e27ef5e8f2b3
BLAKE2b-256 61da9f03f67a1bfcbd04baacf1586b1964aa386800fba8b5e7ff456ebff77c99

See more details on using hashes here.

Provenance

The following attestation bundles were made for regstack-0.2.0.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.0-py3-none-any.whl.

File metadata

  • Download URL: regstack-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 110.8 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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5cc95462c731a603de643a84a8ec82e4df33c65c6074769154c09aeb49f0becd
MD5 1c00870d91de4ff3aefc39817148af59
BLAKE2b-256 04739a0017fc41d31643026cbc617a6621a6eee6ab7fd1b4d8183edcdf7a4c4f

See more details on using hashes here.

Provenance

The following attestation bundles were made for regstack-0.2.0-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