Authentication platform repository containing:
- a central auth service you can deploy once for your organization
- a Python SDK (
auth-service-sdk) that other apps can install to trust and consume that auth service
This repo is designed for a multi-service setup. The auth service owns identity, token issuance, session state, OTP flows, API-key introspection, admin operations, and signing keys. Downstream applications install the SDK and use middleware/dependencies to validate tokens and enforce authorization locally while delegating trust to the central auth service.
The service in app/ is the backend authority for authentication and
authorization-related state. It provides:
- email/password signup and login
- JWT access and refresh token issuance
- audience-scoped tokens for downstream services
- logout and server-side session validation
- API key issuance and introspection
- OTP login challenges and action tokens
- email verification and password reset flows
- re-authentication for sensitive actions
- Google OAuth and SAML entry points
- admin APIs for users, audit logs, OAuth clients, API keys, signing keys, and webhooks
- signing-key rotation and JWKS publishing
- audit logging, rate limiting, health checks, and scheduled retention purge
The SDK lives in sdk/ and is published as auth-service-sdk.
Installing the SDK does not install or run the auth backend itself. It gives other Python/FastAPI/Starlette services a lightweight client-side integration layer so they can trust the central auth service.
The SDK provides:
JWTAuthMiddlewareVerifies RS256 JWTs using the auth service JWKS, enforces token audience, and validates session state through the auth service.APIKeyAuthMiddlewareValidates opaque API keys through auth-service introspection with local positive/negative caching.require_role(...)Route dependency for role-based authorization.require_action_token(...)Route dependency for step-up actions protected by action tokens.require_fresh_auth(...)Route dependency for enforcing recent authentication viaauth_time.
The intended architecture is:
[ User / Client ]
|
v
[ Central Auth Service ] -> issues JWTs, refresh tokens, API key decisions
|
+--> Postgres
+--> Redis
+--> webhook worker / scheduler
|
v
[ Downstream Apps ]
|
+--> install `auth-service-sdk`
+--> validate JWTs/API keys
+--> enforce roles / action tokens / fresh auth
Typical request flow:
- A user authenticates against the auth service.
- The auth service issues an access token for a specific audience such as
orders-api. - The user calls a downstream app with that token.
- The downstream app uses
auth-service-sdkmiddleware to validate the token. - The SDK may call the auth service for JWKS, session validation, or API-key introspection.
- The downstream app receives a trusted identity in
request.state.user.
Use this repo when you want:
- one shared authentication authority for multiple internal or external apps
- consistent JWT validation across services
- centralized session revocation and token verification
- OTP, password reset, email verification, OAuth, and SAML in one place
- a reusable SDK so downstream services do not duplicate auth code
Example setup:
- auth service deployed at
https://auth.example.com orders-apiexpects audienceorders-apibilling-apiexpects audiencebilling-api
Login for orders-api:
POST /auth/login
{
"email": "user@example.com",
"password": "Password123!",
"audience": "orders-api"
}SDK usage inside orders-api:
from fastapi import FastAPI
from sdk import JWTAuthMiddleware
app = FastAPI()
app.add_middleware(
JWTAuthMiddleware,
auth_base_url="https://auth.example.com",
expected_audience="orders-api",
)This audience boundary prevents a token minted for one downstream service from being replayed against another.
You can install the SDK from:
- a published package index:
pip install auth-service-sdk - a local path during development:
pip install /path/to/authSDK/sdk - a Git repository subdirectory:
pip install "git+https://github.com/<org>/<repo>.git#subdirectory=sdk"
The package name is auth-service-sdk, while the import namespace is sdk.
- New engineer onboarding path:
docs/README.md - Local stack setup:
DEVELOPMENT.md - SDK middleware usage:
sdk/README.md
- Copy environment template:
cp .env-sample .env- Start stack:
docker compose -f docker/docker-compose.yml up --build- Verify health:
curl http://localhost:8000/health/readyFull step-by-step guide: DEVELOPMENT.md.
The service is exposed at http://localhost:8000.
Mailhog is exposed at http://localhost:8025 for verification-email inspection.
- Integrate SDK in a service:
docs/integrate-sdk.md - Review auth endpoint contracts:
docs/service-api.md - Review production operations:
docs/operations.md - Debug common integration issues:
docs/troubleshooting.md
Rotate RS256 signing keys:
python -m app.cli rotate-signing-keyOptional overlap override:
python -m app.cli rotate-signing-key --overlap-seconds 900Downstream apps using the SDK expect the auth service to expose:
GET /.well-known/jwks.jsonGET /auth/validatePOST /auth/introspect
Those endpoints are implemented by this repo's auth service.
-
CI(.github/workflows/ci.yml)- Runs on pull requests and pushes to
main. - Executes:
rufflintblack --checkpytestalembic upgrade head --sqlalembic upgrade headagainst CI Postgres servicepython -m build
- Boots Postgres and Redis service containers.
- Generates ephemeral RSA keys at runtime for
JWT__PRIVATE_KEY_PEMandJWT__PUBLIC_KEY_PEM.
- Runs on pull requests and pushes to
-
Publish Container(.github/workflows/release.yml)- Runs on pushes to
main, tags (v*), and manual dispatch. - Builds and pushes the auth-service container image to GHCR.
- Publishes branch, tag, and commit-sha tags automatically.
- Publishes
latestfrom the default branch, or during manual dispatch when explicitly requested. - Uses GitHub Actions cache for faster rebuilds.
- If
docker/Dockerfileis still empty, it exits with a warning and skips image publishing.
- Runs on pushes to
image_nameinPublish Containerworkflow dispatch- Overrides the default GHCR image name (
auth-service).
- Overrides the default GHCR image name (
publish_latestinPublish Containerworkflow dispatch- Forces publication of the
latesttag during manual runs.
- Forces publication of the
Once the workflow has published an image, you can pull it with:
docker pull ghcr.io/<owner>/auth-service:mainFor release tags:
docker pull ghcr.io/<owner>/auth-service:v1.0.0