Skip to main content

Oxaigen Auth SDK Guide

This project is a minimal FastAPI backend that demonstrates how to protect endpoints with the oxaigen-auth SDK.

Use this document as a shareable integration guide for teams that want to add Oxaigen authentication to their own backend app.

What this SDK gives you

  • Request middleware that enriches each request with auth context.
  • A get_current_user dependency for authenticated routes.
  • A get_current_user_optional dependency for mixed public/private routes.
  • A require_permission("<permission>") dependency for role/permission checks.
  • A typed User model injected into your endpoint handlers.

Requirements

  • Python 3.11+
  • FastAPI app
  • An Oxaigen environment/proxy available for token verification

Install

With Poetry:

poetry add oxaigen-auth

With pip:

pip install oxaigen-auth

For local development with the auth mock server (oxaigen-auth-mock), install the mock extra, which adds uvicorn:

pip install "oxaigen-auth[mock]"
from oxaigen_auth import (
    User,
    get_current_user,
    get_current_user_optional,
    require_permission,
    OxaigenAuthMiddleware,
)

Available root exports include:

  • Main API: User, get_current_user, get_current_user_optional, require_permission, OxaigenAuthMiddleware
  • Settings and exceptions: OxaigenAuthSettings, OxaigenAuthUnauthenticatedError, OxaigenAuthPermissionDeniedError, OxaigenAuthUpstreamError
  • Advanced utilities: ProxyAuthClient, aclose_client, extract_bearer_token, derive_proxy_base_url

Minimal FastAPI integration

from typing import Optional
from fastapi import FastAPI, Depends
from oxaigen_auth import OxaigenAuthMiddleware
from oxaigen_auth import (
    User,
    get_current_user,
    get_current_user_optional,
    require_permission,
)

app = FastAPI()
app.add_middleware(OxaigenAuthMiddleware)


@app.get("/v1/me")
async def me(user: User = Depends(get_current_user)):
    return user


@app.get("/v1/maybe-public")
async def maybe_public(user: Optional[User] = Depends(get_current_user_optional)):
    if user:
        return {"signed_in": True, "email": user.email}
    return {"signed_in": False}


@app.get("/v1/audit")
async def audit(user: User = Depends(require_permission("audit"))):
    return {"audit_log": [{"hello": "world"}]}

Behavior model

Important: middleware and dependencies have different responsibilities.

  • OxaigenAuthMiddleware:

    • Parses incoming auth context.
    • Enriches request state with user/auth metadata when present.
    • Does not block unauthenticated requests on its own.
  • get_current_user:

    • Enforces authentication.
    • Returns the authenticated User.
    • Fails the request when token/user validation fails.
  • get_current_user_optional:

    • Returns User when token is valid.
    • Returns None when token is missing/invalid.
    • Still fails with 502 when auth upstream is unavailable.
  • require_permission("..."):

    • Enforces both authentication and permission presence.
    • Use for routes that require explicit capabilities (for example audit).
    • Validates permission name format: [A-Za-z0-9_-]+.

Authenticated request flow

  1. Client sends request with auth cookie/token.
  2. Middleware runs and prepares auth request context.
  3. Endpoint dependency (get_current_user or require_permission) validates against Oxaigen auth backend.
  4. Endpoint executes with resolved User.

Token extraction order:

  1. Authorization: Bearer <token> header
  2. Auth cookie (configured name)

Caching behavior

The SDK caches per process to reduce upstream traffic:

  • User cache: token hash -> User (CACHE_TTL_SECONDS, default 30s)
  • Permission cache: token hash + permission -> bool (CACHE_TTL_SECONDS, default 30s)
  • Negative cache for invalid tokens: token hash sentinel (NEGATIVE_CACHE_TTL_SECONDS, default 5s)

Notes:

  • Cache keys use a hash of the token (not the raw token).
  • Invalid token bursts are throttled by the negative cache.
  • Middleware and dependencies share the same validation/cache pipeline.

SDK configuration (optional)

All env vars are optional with safe defaults:

Var Default Purpose
OXAIGEN_AUTH_PROXY_URL_OVERRIDE unset Force a specific proxy URL. Default: derived from Host header.
OXAIGEN_AUTH_PROXY_SCHEME https Scheme when deriving proxy URL. Set http for dev.
OXAIGEN_AUTH_ACCESS_TOKEN_COOKIE_NAME OxaigenPlatformAuthAccessToken Match if the proxy uses a custom cookie name.
OXAIGEN_AUTH_CACHE_TTL_SECONDS 30 Validation cache TTL.
OXAIGEN_AUTH_NEGATIVE_CACHE_TTL_SECONDS 5 TTL for failed-validation entries.
OXAIGEN_AUTH_CACHE_MAX_ENTRIES 1024 LRU cap.
OXAIGEN_AUTH_PROXY_TIMEOUT_SECONDS 5.0 Server-to-server HTTP timeout.

Tip: for local/dev environments behind non-standard host routing, OXAIGEN_AUTH_PROXY_URL_OVERRIDE is commonly the most useful setting.

Local auth mock server

The package ships a development mock at oxaigen_auth/dev/mock_server.py that emulates the proxy's /_oxa_auth/* surface (login, callback, token exchange, get-me, permission checks) so you can run your backend end-to-end without a real proxy or Keycloak. Start it with uv run oxaigen-auth-mock (or poetry run oxaigen-auth-mock).

See docs/DEVELOPMENT.md for the full setup: built-in personas, env vars, frontend dev-server proxy config, and troubleshooting.

Advanced usage

Most apps only need dependencies + middleware. Advanced consumers can use:

  • ProxyAuthClient for direct low-level proxy calls
  • extract_bearer_token and derive_proxy_base_url for custom flows
  • aclose_client to close SDK HTTP resources during app shutdown

Production recommendations

  • Keep /health public; protect business endpoints with dependencies.
  • Use short timeout/cache defaults unless you have measured reasons to change.
  • Add integration tests for:
    • unauthenticated access (expect failure),
    • authenticated access (expect success),
    • missing permission (expect failure),
    • required permission present (expect success).

Deployment expectations

Your app must be served behind the Oxaigen proxy so /_oxa_auth/* endpoints are available on the same host as the frontend.

If those endpoints are unavailable, SDK auth checks cannot succeed.


Local development setup (two-terminal flow)

When developing a backend app that uses the Oxaigen Auth SDK, you typically run two processes side by side:

  1. The auth mock server — emulates the proxy's /_oxa_auth/* endpoints that the SDK calls to validate tokens.
  2. Your backend application — the FastAPI app that imports the SDK.

This is necessary because in production, your app sits behind the Oxaigen proxy and the SDK resolves /_oxa_auth/* on the request's own Host. Locally there is no proxy in front, so the SDK needs to be told to call the mock instead. That's what OXAIGEN_AUTH_DEV_MODE is for.

Terminal 1 — start the mock server

poetry run oxaigen-auth-mock

This boots the mock on http://127.0.0.1:8765 and serves the full /_oxa_auth/* surface (login, callback, token-exchange, get-me, test-app-permission, etc.). Leave this running.

Terminal 2 — run your backend with the SDK in dev mode

Set OXAIGEN_AUTH_DEV_MODE=1 so the SDK routes validation calls to the mock instead of deriving the URL from the incoming request's Host:

export OXAIGEN_AUTH_DEV_MODE=1
# Optional — only set if your mock isn't on the default 127.0.0.1:8765
# export OXAIGEN_AUTH_DEV_PROXY_URL=http://127.0.0.1:8765

poetry run uvicorn my_app.main:app --reload --port 8000

Your backend now runs on http://127.0.0.1:8000 and every SDK validation call (/_oxa_auth/get-me, /_oxa_auth/test-app-permission/...) goes to the mock on 127.0.0.1:8765.

How the SDK picks the auth URL

The SDK's derive_proxy_base_url resolves in this order:

  1. OXAIGEN_AUTH_PROXY_URL_OVERRIDE — if set, used verbatim. Wins over everything, including dev mode. Useful for pointing at a fixed staging proxy.
  2. OXAIGEN_AUTH_DEV_MODE=1 — uses OXAIGEN_AUTH_DEV_PROXY_URL (default http://127.0.0.1:8765). This is the normal local-dev path.
  3. Default (production) — builds {scheme}://{host} from the incoming request's X-Forwarded-Host or Host header, assuming the app is behind the Oxaigen proxy.

So in dev you generally only need OXAIGEN_AUTH_DEV_MODE=1; the default OXAIGEN_AUTH_DEV_PROXY_URL already matches the mock's default bind address.

Sending requests against your dev backend

With the mock running, the default token mock-dev-token is valid. You can hit your backend directly:

curl -H "Authorization: Bearer mock-dev-token" http://127.0.0.1:8000/v1/me

The SDK will pull the bearer token off the header, call the mock at http://127.0.0.1:8765/_oxa_auth/get-me, and resolve a User. If you're driving a frontend against the mock, the access cookie set by the mock's callback flow will also be accepted by the SDK on same-origin requests.

Tips

  • If you change mock env vars (e.g. OXAIGEN_AUTH_MOCK_PERMISSIONS), restart Terminal 1 — the mock reads env at startup.
  • Token validation results are cached for 30s by default. If you flip a token between valid and invalid while testing, either wait out the TTL or restart your backend.
  • Running the mock on a non-default host/port? Set OXAIGEN_AUTH_DEV_PROXY_URL in Terminal 2 to match (e.g. http://127.0.0.1:9000), and also set OXAIGEN_AUTH_MOCK_HOST/OXAIGEN_AUTH_MOCK_PORT in Terminal 1.
  • To temporarily point dev traffic at a remote staging proxy instead of the local mock, unset OXAIGEN_AUTH_DEV_MODE and set OXAIGEN_AUTH_PROXY_URL_OVERRIDE=https://your-staging-host — no other changes needed.

Metadata

Release files for oxaigen-auth 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for oxaigen-auth 0.1.0
File Size Uploaded Provenance Actions
oxaigen_auth-0.1.0.tar.gz 33.0 kB Without provenance Details for oxaigen_auth-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for oxaigen-auth 0.1.0
File Interpreter ABI Platform Actions
oxaigen_auth-0.1.0-py3-none-any.whl Python 3 none any Details for oxaigen_auth-0.1.0-py3-none-any.whl

Total release size: 71.4 kB

Release files / oxaigen_auth-0.1.0.tar.gz

Download URL oxaigen_auth-0.1.0.tar.gz
Size 33.0 kB
Tags Source
SHA-256 checksum
How to use checksums
4140f36130ed3635ca603bc00b59581424788f039a4f10c229d1f2a71af0e5b0
BLAKE2b-256 checksum
How to use checksums
50752fab80b3c704eeb7f17bc1244b2896e8f02649c290328eeb76b568a311f7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.10.12 Darwin/24.3.0

Release files / oxaigen_auth-0.1.0-py3-none-any.whl

Download URL oxaigen_auth-0.1.0-py3-none-any.whl
Size 38.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cafceb6e131fab3f3735ac42fb45d499e5e19c24c4f7ad96cb696811b1964202
BLAKE2b-256 checksum
How to use checksums
5e06c6f9692d9d716f493627b6442196d24859c8ba92ebc6a2adfe701cc2f775
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.10.12 Darwin/24.3.0

Security for oxaigen-auth 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page