Metadata-Version: 2.4
Name: fastapi-fabric-auth
Version: 0.1.0
Summary: JWT auth, local login, OIDC SSO, API keys, service accounts, and user management for FastAPI.
Project-URL: Homepage, https://git.punakawanlab.id/PunakawanLab/fastapi-fabric
Project-URL: Repository, https://git.punakawanlab.id/PunakawanLab/fastapi-fabric
Author-email: Yoiq S Rambadian <yoiqsram@punakawanlab.id>
License-Expression: MIT
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 :: HTTP Servers
Classifier: Topic :: System :: Systems Administration :: Authentication/Directory
Requires-Python: >=3.10
Requires-Dist: argon2-cffi>=25.1.0
Requires-Dist: fastapi-fabric-core<0.2.0,>=0.1.0
Requires-Dist: passlib[argon2]>=1.7.4
Requires-Dist: pyjwt>=2.0
Description-Content-Type: text/markdown

# fastapi-fabric-auth

JWT authentication, local login, OIDC SSO, API keys, service accounts, and user management for FastAPI.

## Install

```bash
pip install fastapi-fabric[auth]
```

## Routers

Mount only what your app needs:

```python
from fastapi_fabric.auth import create_auth_router                       # login, logout, activate, password reset, me
from fastapi_fabric.auth.users import create_users_router                # user CRUD, activation, sessions
from fastapi_fabric.auth.api_keys import create_api_keys_router
from fastapi_fabric.auth.service_accounts import create_service_accounts_router

app.include_router(create_auth_router())
app.include_router(create_users_router())
app.include_router(create_api_keys_router())
app.include_router(create_service_accounts_router())
```

## Endpoints

| Method | Path | Description |
|---|---|---|
| `POST` | `/api/v1/auth/token` | Local login (`grant_type=password`) or token refresh (`grant_type=refresh_token`) |
| `POST` | `/api/v1/auth/logout` | Revoke current session |
| `GET` | `/api/v1/auth/me` | Current principal info |
| `GET` | `/api/v1/users` | List users (`users:list`) |
| `POST` | `/api/v1/users` | Create user (`users:create`) |
| `PATCH` | `/api/v1/users/{username}` | Update user (`users:modify`) |
| `POST` | `/api/v1/users/{username}/deactivate` | Deactivate user (`users:deactivate`) |
| `POST` | `/api/v1/users/{username}/reactivate` | Reactivate user (`users:deactivate`) |
| `POST` | `/api/v1/users/{username}/password` | Change password (self, or `users:modify`) |
| `GET` | `/api/v1/users/{username}/sessions` | List active sessions (self, or `users:read`) |
| `GET` | `/api/v1/users/{username}/api-keys` | List a user's API keys (`api_keys:list`) |
| `POST` | `/api/v1/users/{username}/api-keys` | Create a scoped API key for a user (`api_keys:create`) |
| `GET` | `/api/v1/service-accounts` | List service accounts (`service_accounts:read`) |
| `POST` | `/api/v1/service-accounts` | Create service account (`service_accounts:create`) |

## Protecting routes

```python
from fastapi_fabric.auth.dependencies import CurrentPrincipal, get_current_principal

@app.get("/protected")
async def protected(principal: CurrentPrincipal = Depends(get_current_principal)):
    return {"user": principal.email}
```

Supports three credential types, resolved automatically:
- `Authorization: Bearer <jwt>`
- `X-API-Key: <key>`
- Cookie: `access_token=<jwt>` (with CSRF protection)

## API keys

```python
# Create a key scoped to specific permissions
POST /api/v1/users/{username}/api-keys
{
  "name": "ci-deploy",
  "scopes": ["audit:read", "users:read"],
  "expires_in_days": 90
}
```

The raw key is returned once at creation and never stored. Subsequent requests match against its hash.

## Service accounts

Machine principals with their own API keys and role assignments. Useful for inter-service authentication.

```python
POST /api/v1/service-accounts
{ "name": "data-pipeline", "description": "nightly ETL job" }

# Issue an API key for the service account
POST /api/v1/service-accounts/{id}/api-keys
{ "name": "prod-key", "expires_in_days": 365 }
```

## OIDC SSO

Configure in `config.yaml`:

```yaml
auth:
  providers:
    oidc:
      issuer: "https://accounts.google.com"
      client_id: "your-client-id"
      client_secret: "your-client-secret"
      redirect_uri: "https://yourapp.com/api/v1/auth/oidc/callback"
      jit_provisioning: true
```

Mount the OIDC router alongside the local-auth router:

```python
from fastapi_fabric.auth import create_oidc_router

app.include_router(create_oidc_router())
```

Users are created automatically (JIT) on first login and synced on subsequent logins.

## Startup seeding

```python
from fastapi_fabric.auth.seeds import upsert_system_admin

async for session in get_session():
    await upsert_system_admin(session, config)
    await session.commit()
```

Creates the system admin account if it does not exist. The system admin bypasses all permission checks.

## Config reference

```yaml
auth:
  secret_key: "32-char-minimum"          # required — signs JWTs
  system_admin_password: "changeme"      # required — sysadmin password
  access_token_expire: 900               # seconds (default 15 min)
  refresh_token_expire: 86400            # seconds (default 1 day)

server:
  secure_cookies: true                   # set false for local HTTP dev
```
