Metadata-Version: 2.4
Name: authwarden
Version: 1.0.0
Summary: A production-grade, pluggable authentication library for FastAPI — JWT, OAuth2 (8 providers), MFA, RBAC, and full flow flexibility (email/SMS, link/OTP, multi-identifier login).
Project-URL: Homepage, https://github.com/timihack/authwarden
Project-URL: Repository, https://github.com/timihack/authwarden
Project-URL: Issues, https://github.com/timihack/authwarden/issues
Project-URL: Changelog, https://github.com/timihack/authwarden/releases
Author: John Adeniran (timihack)
License: MIT
License-File: LICENSE
Keywords: authentication,fastapi,jwt,mfa,oauth2,rbac,security
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP :: Session
Classifier: Topic :: Security :: Cryptography
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: aiosmtplib>=3.0.0
Requires-Dist: authlib>=1.3.0
Requires-Dist: cryptography>=42.0.0
Requires-Dist: fastapi>=0.110.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: itsdangerous>=2.1.0
Requires-Dist: pwdlib[argon2,bcrypt]>=0.2.0
Requires-Dist: pydantic-settings>=2.0.0
Requires-Dist: pydantic[email]>=2.0.0
Requires-Dist: pyjwt>=2.8.0
Requires-Dist: pyotp>=2.9.0
Requires-Dist: python-multipart>=0.0.9
Provides-Extra: all
Requires-Dist: boto3>=1.34.0; extra == 'all'
Requires-Dist: redis>=5.0.0; extra == 'all'
Provides-Extra: dev
Requires-Dist: boto3>=1.34.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: redis>=5.0.0; extra == 'dev'
Requires-Dist: respx>=0.21.0; extra == 'dev'
Provides-Extra: redis
Requires-Dist: redis>=5.0.0; extra == 'redis'
Provides-Extra: sns
Requires-Dist: boto3>=1.34.0; extra == 'sns'
Description-Content-Type: text/markdown

<div align="center">

# authwarden

**A production-grade, pluggable authentication library for FastAPI.**

[![PyPI version](https://img.shields.io/pypi/v/authwarden.svg)](https://pypi.org/project/authwarden/)
[![Python versions](https://img.shields.io/pypi/pyversions/authwarden.svg)](https://pypi.org/project/authwarden/)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/timihack/authwarden/blob/main/LICENSE)
[![Tests](https://img.shields.io/badge/tests-390%20passing-brightgreen.svg)](https://github.com/timihack/authwarden)

JWT auth, OAuth2 across 8 providers, MFA, RBAC, and full flow flexibility — all behind a clean FastAPI router you can drop into any app.

[Quickstart](#quickstart) · [Features](#features) · [Documentation](https://timihack.github.io/authwarden) · [Roadmap](https://github.com/timihack/authwarden/discussions)

</div>

---

## Why authwarden

Most FastAPI auth tutorials show you a toy JWT example and stop there. authwarden is built for the parts that actually matter in production:

- **Everything is a `Protocol`.** Bring your own database (the `AbstractUserStore` protocol works out of the box with SQLAlchemy, MongoDB/Beanie, SQLModel, or Tortoise — no built-in ORM lock-in), your own email/SMS provider, your own templates.
- **Flexibility where it counts.** Verify by link or OTP. Notify by email, SMS, or both. Let users log in with email, username, or phone — your call, configured once.
- **Security defaults that are actually defaults.** Brute-force lockout, OTP attempt limiting, encrypted OAuth tokens at rest, PKCE on every social login flow — none of it bolted on, none of it optional homework.
- **A real test suite.** 390 tests across unit, flow, and full HTTP end-to-end coverage.

---

## Features

**Authentication**
- Register, login, logout, refresh (with rotation)
- Email verification — link or OTP, your choice
- Password reset — link or OTP, your choice
- Change password, and `set-password` for OAuth-only accounts
- Login via email, username, or phone — configurable priority order
- Email *and* SMS notification channels, independently configurable

**MFA**
- TOTP setup, confirm, disable
- 8 single-use, argon2-hashed backup codes per user

**Permissions**
- Role hierarchy (`guest` → `user` → `moderator` → `admin` → `superadmin`)
- Arbitrary scope strings (`"user:read"`, `"admin:delete"`, anything you want)

**OAuth 2.0 / Social Login**
- Google, GitHub, Facebook, Microsoft, LinkedIn, Discord, Twitter/X, Apple
- PKCE (S256) on every provider, no exceptions
- Automatic account linking (existing link → email match → auto-register)
- Apple's quirks handled for you: ES256 client-secret generation, JWKS-cached `id_token` verification, first-login-only name capture
- OAuth tokens encrypted at rest

**Security**
- Login lockout after configurable failed attempts
- OTP attempt limiting with auto-invalidation
- Anti-enumeration on password reset and resend-verification
- Single-use, hashed reset/verification tokens — raw tokens never touch storage

---

## Installation

```bash
pip install authwarden
```

Optional extras:

```bash
pip install "authwarden[redis]"   # Redis-backed sessions and token blacklist
pip install "authwarden[sns]"     # AWS SNS SMS backend
pip install "authwarden[all]"     # everything
```

---

## Quickstart

```python
from fastapi import FastAPI, Depends
from authwarden import AuthWarden, WardenConfig, MemoryUserStore

config = WardenConfig(
    secret_key="change-me-to-a-real-32-byte-secret",
    require_email_verification=False,  # skip for this example
)
store = MemoryUserStore()  # swap for your own AbstractUserStore in production
warden = AuthWarden(config=config, user_store=store)

app = FastAPI()
app.include_router(warden.router, prefix="/auth", tags=["auth"])


@app.get("/profile")
async def profile(user=Depends(warden.current_user)):
    return {"id": user.id, "email": user.email}


@app.delete("/admin/users/{user_id}")
async def delete_user(user_id: str, _=Depends(warden.require_roles("admin"))):
    ...
```

Run it:

```bash
uvicorn main:app --reload
```

Open `http://127.0.0.1:8000/docs` — you now have working `/auth/register`, `/auth/login`, `/auth/refresh`, MFA, and OAuth endpoints, plus an interactive **Authorize** button for testing protected routes.

---

## Core concepts

### `WardenConfig`
Every behavioral switch lives here — verification method (link/OTP), notification channels, login identifier order, lockout thresholds, OAuth provider credentials, and more. See the [full configuration reference](https://timihack.github.io/authwarden) for every field.

### `AbstractUserStore`
A `Protocol`, not a base class — any object with the right async methods satisfies it. Works with any database:

```python
class SQLAlchemyUserStore:
    def __init__(self, session_factory):
        self.session_factory = session_factory

    async def get_by_email(self, email: str):
        async with self.session_factory() as session:
            result = await session.execute(select(UserModel).where(UserModel.email == email))
            row = result.scalar_one_or_none()
            return UserInDB.model_validate(row) if row else None
    # ... remaining protocol methods
```

More examples (MongoDB/Beanie, SQLModel, Tortoise) in the [full docs](https://timihack.github.io/authwarden).

### Extending the user model
`UserInDB` supports arbitrary extra data without a migration, or full subclassing for typed fields:

```python
class MyUser(UserInDB):
    company_id: str | None = None
    subscription_tier: str = "free"
```

### The `AuthWarden` facade
- `warden.router` — mount it, get 20 endpoints
- `warden.current_user` — `Depends()`-compatible, fetches fresh from your store, checks `is_active` on every request
- `warden.require_roles(*roles)` / `warden.require_scopes(*scopes)` — guard any route you write yourself

---

## Testing

```bash
git clone https://github.com/timihack/authwarden
cd authwarden
pip install -e ".[dev]"
pytest
```

390 tests across foundation, auth flows, MFA/permissions, OAuth, router assembly, and full HTTP end-to-end coverage.

---

## Documentation

This README gets you to a working quickstart. For the complete reference — every config field, every flow with code samples, every customization pattern — see the [full documentation site](https://timihack.github.io/authwarden).

## Roadmap

Tracked in the [project discussion](https://github.com/timihack/authwarden/discussions) — includes planned post-v1.0 work like transport/strategy pluggability, Enterprise OIDC, SAML 2.0, and built-in ORM backend implementations.

## Contributing

Issues and PRs welcome. This project is in active development — check the roadmap discussion before starting major work.

## License

MIT © [timihack](https://github.com/timihack)