Metadata-Version: 2.4
Name: apikeyauth
Version: 0.1.1
Summary: Drop-in API key authentication for FastAPI
License: MIT
Project-URL: Repository, https://github.com/shahabRDZ/apikeyauth
Keywords: fastapi,api-key,authentication,security,middleware
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastapi>=0.100.0
Dynamic: license-file

<!-- Downloads: https://pepy.tech/project/apikeyauth -->
<h1 align="center">apikeyauth</h1>

<p align="center">
  <strong>Drop-in API key authentication for FastAPI</strong>
</p>

<p align="center">
  <img src="https://img.shields.io/badge/python-3.10+-blue?logo=python&logoColor=white" />
  <img src="https://img.shields.io/badge/FastAPI-0.100+-009688?logo=fastapi&logoColor=white" />
  <img src="https://img.shields.io/badge/license-MIT-green" />
</p>

---

## Install

```bash
pip install apikeyauth
```

## Usage

```python
from fastapi import FastAPI, Depends
from apikeyauth import APIKeyAuth, MemoryKeyStore, KeyInfo

store = MemoryKeyStore({
    "sk_live_abc123": KeyInfo(name="Production App", scopes=["read", "write"]),
    "sk_test_xyz789": KeyInfo(name="Test App", scopes=["read"]),
})
auth = APIKeyAuth(store)

app = FastAPI()

@app.get("/data")
async def get_data(key: KeyInfo = Depends(auth)):
    return {"hello": key.name, "scopes": key.scopes}
```

Clients authenticate via header or query param:
```bash
# Header
curl -H "X-API-Key: sk_live_abc123" http://localhost:8000/data

# Query param
curl http://localhost:8000/data?api_key=sk_live_abc123
```

## Features

| Feature | Description |
|---------|-------------|
| Header auth | `X-API-Key` header (configurable name) |
| Query auth | `?api_key=` query param (configurable name) |
| Flexible auth | Checks header first, falls back to query |
| Key metadata | Name, scopes, rate limit, owner, custom metadata |
| Pluggable store | Implement `KeyStore` for database/Redis backends |
| Memory store | Built-in dict-based store with add/revoke |

## Custom Backend

```python
from apikeyauth import KeyStore, KeyInfo

class DatabaseKeyStore(KeyStore):
    async def validate(self, key: str) -> KeyInfo | None:
        row = await db.fetch_one("SELECT * FROM api_keys WHERE key_hash = $1", hash(key))
        if row:
            return KeyInfo(name=row["name"], scopes=row["scopes"].split(","))
        return None
```

## License

MIT
