
Security News
Deno 2.6 + Socket: Supply Chain Defense In Your CLI
Deno 2.6 introduces deno audit with a new --socket flag that plugs directly into Socket to bring supply chain security checks into the Deno CLI.
fastapi-api-key
Advanced tools
fastapi-api-key provides secure, production-ready API key management for FastAPI. It offers pluggable hashing strategies (Argon2 or bcrypt), backend-agnostic persistence (currently SQLAlchemy), and an optional cache layer (aiocache). Includes a Typer CLI and a FastAPI router for CRUD management of keys.
fastapi-api-key provides a backend-agnostic library that provides a production-ready, secure API key system, with optional FastAPI and Typer connectors.
This library try to follow best practices and relevant RFCs for API key management and authentication:
Authorization: Bearer <api_key> header for
key transmission (also supports deprecated X-API-Key header and api_key query param)This project is not published to PyPI. Use a tool like uv to manage dependencies.
uv add fastapi-api-key
uv pip install fastapi-api-key
Clone or fork the repository and install the project with the extras that fit your stack. Examples below use uv:
uv sync --extra all # fastapi + sqlalchemy + argon2 + bcrypt
uv pip install -e ".[all]"
For lighter setups you can choose individual extras:
| Installation mode | Command | Description |
|---|---|---|
| Base installation | fastapi-api-key | Installs the core package without any optional dependencies. |
| With Bcrypt support | fastapi-api-key[bcrypt] | Adds support for password hashing using bcrypt |
| With Argon2 support | fastapi-api-key[argon2] | Adds support for password hashing using Argon2 |
| With SQLAlchemy support | fastapi-api-key[sqlalchemy] | Adds database integration via SQLAlchemy |
| With Cache Service support | fastapi-api-key[aiocache] | Adds database integration via Aiocache |
| Core setup | fastapi-api-key[core] | Installs the core dependencies (SQLAlchemy + Argon2 + bcrypt + aiocache |
| FastAPI only | fastapi-api-key[fastapi] | Installs FastAPI as an optional dependency |
| Full installation | fastapi-api-key[all] | Installs all optional dependencies |
uv add fastapi-api-key[sqlalchemy]
uv pip install fastapi-api-key[sqlalchemy]
uv sync --extra sqlalchemy
uv pip install -e ".[sqlalchemy]"
Development dependencies (pytest, ruff, etc.) are available under the dev group:
uv sync --extra dev
uv pip install -e ".[dev]"
Run the full lint suite with the provided Makefile:
make lint
Install make via sudo apt install make on Debian/Ubuntu or choco install make (Git for Windows also ships one) on Windows, then run the command from the project root to trigger Ruff, Ty, Pyrefly, and Bandit through uv run.
import asyncio
from fastapi_api_key import ApiKeyService
from fastapi_api_key.repositories.in_memory import InMemoryApiKeyRepository
async def main():
repo = InMemoryApiKeyRepository()
service = ApiKeyService(repo=repo) # default hasher is Argon2 with a default pepper (to be changed in prod)
entity, api_key = await service.create(name="docs")
print("Give this secret to the client:", api_key)
verified = await service.verify_key(api_key)
print("Verified key belongs to:", verified.id_)
asyncio.run(main())
Override the default pepper in production:
import os
from fastapi_api_key import ApiKeyService
from fastapi_api_key.hasher.argon2 import Argon2ApiKeyHasher
from fastapi_api_key.repositories.in_memory import InMemoryApiKeyRepository
pepper = os.environ["API_KEY_PEPPER"]
hasher = Argon2ApiKeyHasher(pepper=pepper)
repo = InMemoryApiKeyRepository()
service = ApiKeyService(
repo=repo,
hasher=hasher,
)
This is a classic API key if you don't modify the service behavior:
Structure:
{global_prefix}-{separator}-{key_id}-{separator}-{key_secret}
Example:
ak-7a74caa323a5410d-mAfP3l6yAxqFz0FV2LOhu2tPCqL66lQnj3Ubd08w9RyE4rV4skUcpiUVIfsKEbzw
ak (for "Api Key"), to identify the key type (useful to indicate that it is an API key).When verifying an API key, the service extracts the identifier, retrieves the corresponding record from the repository, and compares the hashed secret. If found, it hashes the provided secret (with the same salt and pepper) and compares it to the stored hash. If they match, the key is valid.
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.
This example uses SQLAlchemy with FastAPI. It creates the database tables at startup if they do not exist.
import os
from pathlib import Path
from typing import AsyncIterator
from fastapi import FastAPI, Depends, APIRouter
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
from fastapi_api_key import ApiKey, ApiKeyService
from fastapi_api_key.hasher.argon2 import Argon2ApiKeyHasher
from fastapi_api_key.repositories.sql import SqlAlchemyApiKeyRepository
from fastapi_api_key.api import create_api_keys_router, create_depends_api_key
# Set env var to override default pepper
# Using a strong, unique pepper is crucial for security
# Default pepper is insecure and should not be used in production
pepper = os.getenv("API_KEY_PEPPER")
hasher = Argon2ApiKeyHasher(pepper=pepper)
path = Path(__file__).parent / "db.sqlite3"
database_url = os.environ.get("DATABASE_URL", f"sqlite+aiosqlite:///{path}")
async_engine = create_async_engine(database_url, future=True)
async_session_maker = async_sessionmaker(
async_engine,
class_=AsyncSession,
expire_on_commit=False,
)
app = FastAPI(title="API with API Key Management")
async def inject_async_session() -> AsyncIterator[AsyncSession]:
"""Dependency to provide an active SQLAlchemy async session."""
async with async_session_maker() as session:
async with session.begin():
yield session
async def inject_svc_api_keys(async_session: AsyncSession = Depends(inject_async_session)) -> ApiKeyService:
"""Dependency to inject the API key service with an active SQLAlchemy async session."""
repo = SqlAlchemyApiKeyRepository(async_session)
# Necessary if you don't use your own DeclarativeBase
await repo.ensure_table(async_engine=async_engine)
return ApiKeyService(repo=repo, hasher=hasher)
security = create_depends_api_key(inject_svc_api_keys)
router_protected = APIRouter(prefix="/protected", tags=["Protected"])
router = APIRouter(prefix="/api-keys", tags=["API Keys"])
router_api_keys = create_api_keys_router(
inject_svc_api_keys,
router=router,
)
@router_protected.get("/")
async def read_protected_data(api_key: ApiKey = Depends(security)):
return {
"message": "This is protected data",
"apiKey": {
"id": api_key.id_,
"name": api_key.name,
"description": api_key.description,
"isActive": api_key.is_active,
"createdAt": api_key.created_at,
"expiresAt": api_key.expires_at,
"lastUsedAt": api_key.last_used_at,
},
}
app.include_router(router_api_keys)
app.include_router(router_protected)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="localhost", port=8000)
The router exposes:
POST /api-keys - create a key and return the plaintext secret once.GET /api-keys - list keys with offset/limit pagination.GET /api-keys/{id} - fetch a key by identifier.PATCH /api-keys/{id} - update name, description, or active flag.DELETE /api-keys/{id} - remove a key.FAQs
fastapi-api-key provides secure, production-ready API key management for FastAPI. It offers pluggable hashing strategies (Argon2 or bcrypt), backend-agnostic persistence (currently SQLAlchemy), and an optional cache layer (aiocache). Includes a Typer CLI and a FastAPI router for CRUD management of keys.
We found that fastapi-api-key demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Deno 2.6 introduces deno audit with a new --socket flag that plugs directly into Socket to bring supply chain security checks into the Deno CLI.

Security News
New DoS and source code exposure bugs in React Server Components and Next.js: what’s affected and how to update safely.

Security News
Socket CEO Feross Aboukhadijeh joins Software Engineering Daily to discuss modern software supply chain attacks and rising AI-driven security risks.