Reusable authentication dependency for FastAPI with **API Key** and **JWT Bearer** support.
Project description
fastapi-auth-manager-dep
Reusable authentication dependency for FastAPI with API Key and JWT Bearer support.
- One mandatory ADMIN key via envvar (super-key, always valid)
- Additional api-keys with labels/roles via JSON envvar
- Fine-grained per-endpoint control: which roles each endpoint accepts
- HMAC JWT with configurable algorithms
- Public endpoints via explicit opt-out
Install
pip install fastapi-auth-manager-dep
Environment variables
| Variable | Required | Description |
|---|---|---|
AUTH_ADMIN_API_KEY |
Yes | Administrator api-key. Super-key: valid on every endpoint. |
AUTH_API_KEYS |
No | JSON object mapping api-keys to their labels. See format below. |
AUTH_JWT_SECRET_KEY |
No* | HMAC secret key for verifying user JWTs. Required when using "jwt". |
AUTH_JWT_ALGORITHMS |
No | List of allowed algorithms (default: ["HS256", "HS384", "HS512"]). |
AUTH_API_KEYS format
A JSON object where each key is the raw api-key value and the value is its label/role:
AUTH_API_KEYS='{"key-abc123": "reports", "key-xyz789": "billing", "key-qrs456": "billing"}'
- Multiple keys can share the same label (same role).
- Empty string (
AUTH_API_KEYS="") is equivalent to having no additional keys.
.env example
AUTH_ADMIN_API_KEY=super-secret-admin-key
AUTH_API_KEYS={"key-reports-1": "reports", "key-billing-1": "billing", "key-billing-2": "billing"}
AUTH_JWT_SECRET_KEY=my-jwt-secret-key
Usage
1. Global authentication (entire app)
All endpoints are protected with the ADMIN key by default:
from fastapi import Depends, FastAPI
from fastapi_auth import AuthDependency
app = FastAPI(dependencies=[Depends(AuthDependency())])
2. Restrict by api-key label
Only the ADMIN key and keys labelled "reports" can access:
from fastapi_auth import AuthDependency
@app.get(
"/reports",
dependencies=[Depends(AuthDependency(valid_token_types={"reports"}))]
)
async def get_reports():
...
3. Combine api-key and JWT on the same endpoint
from fastapi_auth import AuthDependency
@app.get(
"/billing",
dependencies=[Depends(AuthDependency(valid_token_types={"billing", "jwt"}))]
)
async def get_billing():
...
4. Allow all additional api-keys
from fastapi_auth import AuthDependency
# Using the AuthDependency.ALL sentinel
@app.get(
"/any",
dependencies=[Depends(AuthDependency(valid_token_types=AuthDependency.ALL))]
)
async def any_key_endpoint():
...
# Equivalent using a string
AuthDependency(valid_token_types="*")
5. Access the authenticated principal inside a handler
AuthDependency returns an AuthPrincipal with the method used, role, and JWT payload:
from fastapi_auth import AuthDependency, AuthPrincipal
@app.get("/me")
async def me(
principal: AuthPrincipal = Depends(
AuthDependency(valid_token_types={"jwt", "billing"})
)
):
return {
"method": principal.method, # "jwt" | "api_key"
"sub": principal.sub, # user_id (JWT) or raw key value (api-key)
"role": principal.role, # "admin" | "reports" | "billing" | None (JWT)
"payload": principal.payload, # full JWT dict | None
}
6. Public endpoint (opt-out of global auth)
When auth is configured globally, use PublicRoute to exclude specific endpoints:
from fastapi_auth import PublicRoute
@app.get("/health", dependencies=[Depends(PublicRoute())])
async def health():
return {"status": "ok"}
valid_token_types behaviour reference
valid_token_types |
ADMIN key | Additional keys | User JWT |
|---|---|---|---|
None (default) |
Yes | No | No |
{"reports"} |
Yes | reports label only |
No |
{"billing", "jwt"} |
Yes | billing label only |
Yes |
AuthDependency.ALL / "*" |
Yes | All | No |
{"jwt"} |
Yes | No | Yes |
The ADMIN key is always valid regardless of the endpoint configuration.
AuthPrincipal — return object
class AuthPrincipal(BaseModel):
method: AuthMethod # AuthMethod.JWT | AuthMethod.AUTH_ADMIN_API_KEY
sub: str # user_id (JWT) or raw api-key value
role: str | None = None # key role/label; None for JWT
payload: dict | None = None # full JWT payload; None for api-key
Error responses
All authentication errors return HTTP 401 Unauthorized with a detail field:
| Situation | detail |
|---|---|
| No credentials provided | "Authentication credentials are required" |
| Api-key not found or not allowed | "Invalid authentication credentials" |
| Expired JWT | "JWT token has expired" |
| Invalid JWT signature | "Invalid JWT token: ..." |
| Disallowed JWT algorithm | "JWT algorithm not allowed: RS256" |
Tests
pip install pytest pytest-asyncio
pytest tests/ -v
Test coverage includes:
- ADMIN key as super-key across endpoints with different restrictions
- Label-based restriction: accepts the correct label, rejects others
- Multiple keys sharing the same label
ALLsentinel and its"*"string equivalent- Valid JWT, expired JWT, JWT ignored when
"jwt"is not enabled - No credentials
AUTH_API_KEYSvalidation in settings (JSON string, dict, invalid JSON)
Full example
from fastapi import Depends, FastAPI
from fastapi_auth import AuthDependency, AuthPrincipal, PublicRoute
app = FastAPI(dependencies=[Depends(AuthDependency())]) # global: ADMIN key only
@app.get("/health", dependencies=[Depends(PublicRoute())])
async def health():
return {"status": "ok"}
@app.get("/reports", dependencies=[Depends(AuthDependency(valid_token_types={"reports"}))])
async def reports():
return {"data": "..."}
@app.get("/me")
async def me(
principal: AuthPrincipal = Depends(AuthDependency(valid_token_types={"jwt"}))
):
return {"sub": principal.sub, "payload": principal.payload}
@app.get("/internal", dependencies=[Depends(AuthDependency(valid_token_types=AuthDependency.ALL))])
async def internal():
return {"message": "any valid api-key accepted"}
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fastapi_auth_manager_dep-0.1.0.tar.gz.
File metadata
- Download URL: fastapi_auth_manager_dep-0.1.0.tar.gz
- Upload date:
- Size: 11.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
802b920891ab190894c3084782a6b17fc3316116573008878efa9bbce18b6a9e
|
|
| MD5 |
b49e853e60d940397befd5ec9974cb88
|
|
| BLAKE2b-256 |
9f976cd9247204f6ae541d84e18edef92bf3a94105e336087775b37fd0f112a2
|
File details
Details for the file fastapi_auth_manager_dep-0.1.0-py3-none-any.whl.
File metadata
- Download URL: fastapi_auth_manager_dep-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c1830f2ea476819c8eb64ba5f9a33371490eabd5b527018c0e1dfa2386fd3d0c
|
|
| MD5 |
1339816ce5f916c4d141b7b08ca192e7
|
|
| BLAKE2b-256 |
25b12a5ec8550791a5fd1f21a6237ab041f85faab54fb893011889fd1790ea4d
|