|
1 | | -# Fastapi Api Key |
| 1 | +# FastAPI Api Key |
| 2 | + |
| 3 | + |
| 4 | +[](https://pytest.org/) |
| 5 | +[](https://pypi.org/project/fastapi-api-key/) |
| 6 | +[](https://athroniaeth.github.io/fastapi-api-key/) |
| 7 | +[](https://codecov.io/gh/Athroniaeth/fastapi-api-key) |
| 8 | +[](https://bandit.readthedocs.io/) |
| 9 | +[](https://docs.astral.sh/uv/) |
| 10 | +[](https://docs.astral.sh/ruff/) |
2 | 11 |
|
3 | 12 | `fastapi-api-key` provides reusable building blocks to issue, persist, and verify API keys in FastAPI applications. It |
4 | 13 | ships with a domain model, hashing helpers, repository contracts, and an optional FastAPI router for CRUD management of |
5 | 14 | keys. |
6 | 15 |
|
| 16 | +## Links |
| 17 | + |
| 18 | +- **Documentation:** [https://athroniaeth.github.io/fastapi-api-key/](https://athroniaeth.github.io/fastapi-api-key/) |
| 19 | +- **PyPI package:** [https://pypi.org/project/fastapi-api-key/](https://pypi.org/project/fastapi-api-key/) |
| 20 | + |
7 | 21 | ## Features |
8 | 22 |
|
9 | 23 | - **Security-first**: secrets are hashed with a salt and a pepper, and never logged or returned after creation |
10 | | -- **Ready-to-use**: just create your repository (storage) and use service |
11 | 24 | - **Prod-ready**: services and repositories are async, and battle-tested |
12 | 25 |
|
13 | 26 | - **Agnostic hasher**: you can use any async-compatible hashing strategy (default: Argon2) |
14 | 27 | - **Agnostic backend**: you can use any async-compatible database (default: SQLAlchemy) |
15 | | -- **Factory**: create a Typer, FastAPI router wired to api key systems (only SQLAlchemy for now) |
| 28 | +- **Connector**: create a Typer, FastAPI router wired to api key systems |
| 29 | + |
| 30 | + |
| 31 | +- **Envvar support**: easily configure peppers and other secrets via environment variables |
| 32 | +- **Extensible**: customize models, repositories, hashers, and services to fit your needs |
| 33 | +- **Scopes support**: assign scopes to API keys for fine-grained access control |
| 34 | + |
| 35 | +## Standards compliance |
| 36 | + |
| 37 | +This library try to follow best practices and relevant RFCs for API key management and authentication: |
| 38 | + |
| 39 | +- **[RFC 9110/7235](https://www.rfc-editor.org/rfc/rfc9110.html)**: Router raise 401 for missing/invalid keys, 403 for |
| 40 | + valid but inactive/expired keys |
| 41 | +- **[RFC 6750](https://datatracker.ietf.org/doc/html/rfc6750)**: Supports `Authorization: Bearer <api_key>` header for |
| 42 | + key transmission (also supports deprecated `X-API-Key` header and `api_key` query param) |
| 43 | + |
| 44 | +## How API Keys Work |
| 45 | + |
| 46 | +### API Key Format |
| 47 | + |
| 48 | +This is a classic API key if you don't modify the service behavior: |
16 | 49 |
|
17 | | -## Installation |
| 50 | +**Structure:** |
18 | 51 |
|
19 | | -This projet does not publish to PyPI. Use a tool like [uv](https://docs.astral.sh/uv/) to manage dependencies. |
| 52 | +`{global_prefix}`-`{delimiter}`-`{identifier}`-`{delimiter}`-`{secret}` |
20 | 53 |
|
21 | | -```bash |
22 | | -uv add fastapi-api-key |
23 | | -uv pip install fastapi-api-key |
24 | | -``` |
| 54 | +**Example:** |
25 | 55 |
|
26 | | -## Development installation |
| 56 | +`ak-7a74caa323a5410d-mAfP3l6yAxqFz0FV2LOhu2tPCqL66lQnj3Ubd08w9RyE4rV4skUcpiUVIfsKEbzw` |
27 | 57 |
|
28 | | -Clone the repository and install the project with the extras that fit your stack. Examples below use `uv`: |
| 58 | +- "-" separators so that systems can easily split |
| 59 | +- Prefix `ak` (for "Api Key"), to identify the key type (useful to indicate that it is an API key). |
| 60 | +- 16 first characters are the identifier (UUIDv4 without dashes) |
| 61 | +- 48 last characters are the secret (random URL-safe base64 string) |
29 | 62 |
|
30 | | -```bash |
31 | | -uv sync --extra all # fastapi + sqlalchemy + argon2 + bcrypt |
32 | | -uv pip install -e ".[all]" |
33 | | -``` |
| 63 | +When verifying an API key, the service extracts the identifier, retrieves the corresponding record from the repository, |
| 64 | +and compares the hashed secret. If found, it hashes the provided secret (with the same salt and pepper) and compares it |
| 65 | +to the stored hash. |
| 66 | +If they match, the key is valid. |
34 | 67 |
|
35 | | -For lighter setups you can choose individual extras: |
| 68 | +### Schema validation |
36 | 69 |
|
37 | | -| Installation mode | Command | Description | |
38 | | -|-----------------------------|-------------------------------|----------------------------------------------------------------------------------| |
39 | | -| **Base installation** | `fastapi-api-key` | Installs the core package without any optional dependencies. | |
40 | | -| **With bcrypt support** | `fastapi-api-key[bcrypt]` | Adds support for password hashing using **bcrypt** (`bcrypt>=5.0.0`). | |
41 | | -| **With Argon2 support** | `fastapi-api-key[argon2]` | Adds support for password hashing using **Argon2** (`argon2-cffi>=25.1.0`). | |
42 | | -| **With SQLAlchemy support** | `fastapi-api-key[sqlalchemy]` | Adds database integration via **SQLAlchemy** (`sqlalchemy>=2.0.43`). | |
43 | | -| **Core setup** | `fastapi-api-key[core]` | Installs the **core dependencies** (SQLAlchemy + Argon2 + bcrypt). | |
44 | | -| **FastAPI only** | `fastapi-api-key[fastapi]` | Installs **FastAPI** as an optional dependency (`fastapi>=0.118.0`). | |
45 | | -| **Full installation** | `fastapi-api-key[all]` | Installs **all optional dependencies**: FastAPI, SQLAlchemy, Argon2, and bcrypt. | |
| 70 | +Here is a diagram showing what happens after you initialize your API key service with a global prefix and delimiter when you provide an API key to the `.verify_key()` method. |
46 | 71 |
|
47 | | -```bash |
48 | | -uv add fastapi-api-key[sqlalchemy] |
49 | | -uv pip install fastapi-api-key[sqlalchemy] |
50 | | -uv sync --extra sqlalchemy |
51 | | -uv pip install -e ".[sqlalchemy]" |
52 | | -``` |
| 72 | +<img src="./schema.svg"> |
53 | 73 |
|
54 | | -Development dependencies (pytest, ruff, etc.) are available under the `dev` group: |
| 74 | +## Additional notes |
55 | 75 |
|
56 | | -```bash |
57 | | -uv sync --extra dev |
58 | | -uv pip install -e ".[dev]" |
59 | | -``` |
| 76 | +- Python 3.9+ is required. |
| 77 | +- The library issues warnings if you keep the default pepper; always configure a secret value outside source control. |
| 78 | +- Never log peppers or plaintext API keys, change the pepper of prod will prevent you from reading API keys |
60 | 79 |
|
61 | 80 | ## What to read next |
62 | 81 |
|
|
0 commit comments