Metadata-Version: 2.4
Name: deadbolt
Version: 0.2.0
Summary: A framework-agnostic, batteries-included authentication library for Python.
Project-URL: Homepage, https://github.com/ruban-s/deadbolt
Project-URL: Documentation, https://deadbolt.readthedocs.io
Project-URL: Source, https://github.com/ruban-s/deadbolt
Project-URL: Issues, https://github.com/ruban-s/deadbolt/issues
Project-URL: Changelog, https://github.com/ruban-s/deadbolt/blob/main/CHANGELOG.md
Author: the deadbolt contributors
License-Expression: MIT
License-File: LICENSE
Keywords: auth,authentication,framework-agnostic,oauth,security,sessions
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: anyio>=4.4
Requires-Dist: argon2-cffi>=23.1
Requires-Dist: cryptography>=43
Requires-Dist: itsdangerous>=2.2
Requires-Dist: sniffio>=1.3
Provides-Extra: all
Requires-Dist: aiosmtplib>=3.0; extra == 'all'
Requires-Dist: django>=4.2; extra == 'all'
Requires-Dist: fastapi>=0.115; extra == 'all'
Requires-Dist: flask>=3.0; extra == 'all'
Requires-Dist: httpx>=0.27; extra == 'all'
Requires-Dist: joserfc>=1.7; extra == 'all'
Requires-Dist: limits>=3.13; extra == 'all'
Requires-Dist: litestar>=2.12; extra == 'all'
Requires-Dist: pyjwt[crypto]>=2.13; extra == 'all'
Requires-Dist: pyotp>=2.9; extra == 'all'
Requires-Dist: redis>=5.0; extra == 'all'
Requires-Dist: sqlalchemy[asyncio]>=2.0; extra == 'all'
Requires-Dist: starlette>=0.40; extra == 'all'
Requires-Dist: webauthn>=2.0; extra == 'all'
Provides-Extra: django
Requires-Dist: django>=4.2; extra == 'django'
Provides-Extra: email
Requires-Dist: aiosmtplib>=3.0; extra == 'email'
Provides-Extra: fastapi
Requires-Dist: fastapi>=0.115; extra == 'fastapi'
Requires-Dist: starlette>=0.40; extra == 'fastapi'
Provides-Extra: flask
Requires-Dist: flask>=3.0; extra == 'flask'
Provides-Extra: jose
Requires-Dist: joserfc>=1.7; extra == 'jose'
Provides-Extra: jwt
Requires-Dist: pyjwt[crypto]>=2.13; extra == 'jwt'
Provides-Extra: litestar
Requires-Dist: litestar>=2.12; extra == 'litestar'
Provides-Extra: oauth
Requires-Dist: httpx>=0.27; extra == 'oauth'
Provides-Extra: passkeys
Requires-Dist: webauthn>=2.0; extra == 'passkeys'
Provides-Extra: ratelimit
Requires-Dist: limits>=3.13; extra == 'ratelimit'
Provides-Extra: redis
Requires-Dist: redis>=5.0; extra == 'redis'
Provides-Extra: sqlalchemy
Requires-Dist: sqlalchemy[asyncio]>=2.0; extra == 'sqlalchemy'
Provides-Extra: starlette
Requires-Dist: starlette>=0.40; extra == 'starlette'
Provides-Extra: totp
Requires-Dist: pyotp>=2.9; extra == 'totp'
Description-Content-Type: text/markdown

# 🔒 deadbolt

A framework-agnostic, batteries-included authentication library for Python. Own your auth, mount it on any framework — no hosted service, no lock-in.

[![PyPI](https://img.shields.io/pypi/v/deadbolt.svg)](https://pypi.org/project/deadbolt/)
[![Python](https://img.shields.io/pypi/pyversions/deadbolt.svg)](https://pypi.org/project/deadbolt/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://opensource.org/license/mit)
![Typed](https://img.shields.io/badge/typed-mypy--strict-blue.svg)

`deadbolt` is what [Better Auth](https://better-auth.com) is for the TypeScript world, rebuilt
idiomatically for Python: a self-hosted auth engine with a database-adapter abstraction, signed
cookie-based sessions, and a plugin system — mountable onto **any** Python web framework.

## Why

- **Framework-agnostic.** One async-first core speaks a normalized request/response contract; a
  ~30-line adapter mounts it on FastAPI, Starlette, Flask, and more. WSGI frameworks are served from
  the async core through a background-loop sync bridge.
- **Bring your own database.** A uniform adapter interface (built on SQLAlchemy 2.0 Core) covers
  Postgres/MySQL/SQLite; an in-memory adapter ships for tests and local dev.
- **Secure by default.** Argon2id hashing, opaque DB-backed sessions stored hashed, signed `__Host-`
  cookies, session rotation, rate limiting, origin-based CSRF checks, and timing-safe sign-in.
- **Alias-first API.** Everything hangs off one object: `import deadbolt as db` → `db.Auth(...)`.

## Install

```bash
pip install deadbolt                          # core (email/password + sessions)
pip install "deadbolt[fastapi,sqlalchemy]"    # + a framework mount + a database adapter
pip install "deadbolt[all]"                   # everything, including every plugin's deps
```

## Quickstart

```python
import deadbolt as db
from deadbolt.integrations.fastapi import mount

auth = db.Auth(
    adapter=db.MemoryAdapter(),                 # or db.SQLAlchemyAdapter(engine)
    secret=SECRET,                              # 32+ random bytes
    email_and_password=db.EmailPassword(enabled=True),
)

# Mount on any framework — this is the whole integration:
mount(app, auth, prefix="/api/auth")

# ...or call endpoints directly, no HTTP:
result = await auth.api.sign_in_email(email="a@b.com", password="…", as_response=True)
```

Add features by dropping in plugins:

```python
from deadbolt.plugins.oauth import social, google
from deadbolt.plugins.totp import totp
from deadbolt.plugins.passkeys import passkeys

auth = db.Auth(
    adapter=db.MemoryAdapter(),
    secret=SECRET,
    email_and_password=db.EmailPassword(enabled=True),
    plugins=[
        social(providers=[google(client_id=..., client_secret=..., redirect_uri=...)]),
        totp(),
        passkeys(rp_id="example.com", rp_name="Example", origin="https://example.com"),
    ],
)
```

## Plugins

| Plugin | Import | What it adds |
|---|---|---|
| Username | `deadbolt.plugins.username` | Sign in with a username |
| Magic link | `deadbolt.plugins.magic_link` | Passwordless email links |
| Email OTP | `deadbolt.plugins.email_otp` | Passwordless email codes |
| Phone OTP | `deadbolt.plugins.phone` | Passwordless SMS codes |
| Social OAuth | `deadbolt.plugins.oauth` | Google, GitHub, or any OAuth2/OIDC provider |
| Passkeys | `deadbolt.plugins.passkeys` | WebAuthn registration + authentication |
| TOTP 2FA | `deadbolt.plugins.totp` | Authenticator apps + backup codes |
| Organizations | `deadbolt.plugins.organization` | Multi-tenancy, RBAC, invitations, teams |
| API keys | `deadbolt.plugins.api_keys` | Machine-to-machine keys |
| Admin | `deadbolt.plugins.admin` | Roles, bans, user management |
| JWT | `deadbolt.plugins.jwt` | Stateless bearer tokens |

## CLI

Generate SQL DDL for your full schema (core plus every enabled plugin) from your `Auth` config:

```bash
deadbolt generate --config myapp.auth:auth --dialect postgresql
```

## Development

```bash
uv sync --all-extras --group dev
uv run pre-commit install
uv run pytest
uv run ruff check . && uv run ruff format --check . && uv run mypy
```

## Security

Please report vulnerabilities via GitHub private advisories — see `SECURITY.md` in the repository.
Never open a public issue for a security bug. The architecture spec and STRIDE threat model live in
the repository's `docs/` directory.

## License

MIT © the deadbolt contributors.
