Skip to main content

Oxaigen Auth SDK

Project description

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

Import paths (recommended)

from oxaigen 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.

How it works

  1. SDK reads Authorization: Bearer <token> from the request, or falls back to the OxaigenPlatformAuthAccessToken cookie.
  2. SDK calls /_oxa_auth/get-me on the proxy (via https://{request_host}) with the token forwarded as Authorization: Bearer.
  3. Proxy validates the token against Keycloak, looks up the user in the platform DB, returns a MeResponse.
  4. SDK parses into a User, caches for 30s keyed on sha256(token).
  5. For require_permission(name), SDK additionally calls /_oxa_auth/test-app-permission/{name}, also cached for 30s.

Where the bearer token comes from

  • Same-origin frontend → backend — the access cookie auto-attaches. The SDK reads it from the cookie.
  • Cross-origin frontend → backend — frontend uses useAccessToken() from @oxaigen/react to read the JS-readable access cookie and forward it as Authorization: Bearer. The SDK reads the header.

HTTP error mapping

Dependencies convert auth failures to FastAPI HTTPException responses:

  • Missing/invalid token -> 401 Unauthorized
  • Missing permission -> 403 Forbidden
  • Auth proxy unavailable / upstream failure -> 502 Bad Gateway

Common pitfalls

  • Adding middleware without using dependencies on routes: endpoints stay publicly accessible.
  • Forgetting permission checks on privileged routes: use require_permission(...).
  • Host/proxy mismatch in local setups: configure OXAIGEN_AUTH_PROXY_URL_OVERRIDE.
  • Using invalid permission names: only [A-Za-z0-9_-]+ is accepted.

User model deep dive

User is the SDK's typed representation of the auth proxy response (/_oxa_auth/get-me), scoped to one workspace and app context.

The model is designed for forward compatibility. If the proxy adds new fields, older SDK clients should keep working without an immediate SDK release.

Why this model is permissive

The auth models intentionally use:

  • Optional fields for most identity/profile values
  • extra = "allow" on auth models

This gives app developers:

  • Typed, stable access for known fields
  • Non-breaking behavior when upstream adds fields
  • Access to newly added proxy fields via user.extra

Structure and semantics

Workspace-scoped models

  • UserWorkspace: workspace identity in scope (id, name)
  • WorkspaceRole: role assignment in the scoped workspace
  • WorkspacePermission: permission assignment in the scoped workspace

All three allow unknown fields, so upstream schema expansion remains non-breaking.

Core identity fields

Common profile fields are optional because availability can vary by identity provider and rollout stage:

  • id, user_name, email
  • account_type (commonly "internal" or "external")
  • enabled, first_name, last_name

Treat these as "present when provided by upstream", not guaranteed invariants.

Authentication state

  • is_authenticated defaults to True for resolved users
  • is_anonymous is a convenience property (not is_authenticated)

In standard dependency-based usage, get_current_user returns authenticated users. Anonymous behavior is mainly relevant in optional/mixed-auth flows and tests.

Authorization data

  • workspace_roles defaults to an empty list
  • workspace_permissions defaults to an empty list

Using default_factory=list avoids mutable-default pitfalls and allows safe iteration even when upstream omits these fields.

Middleware state contract

When OxaigenAuthMiddleware is installed, each request has:

  • request.state.user (User or None)
  • request.state.auth_error (str or None)

The middleware never blocks the request by itself. If upstream auth is down, it sets auth_error and continues; route dependencies decide enforcement.

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

oxaigen_auth-0.0.3.tar.gz (19.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

oxaigen_auth-0.0.3-py3-none-any.whl (21.4 kB view details)

Uploaded Python 3

File details

Details for the file oxaigen_auth-0.0.3.tar.gz.

File metadata

  • Download URL: oxaigen_auth-0.0.3.tar.gz
  • Upload date:
  • Size: 19.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.5.1 CPython/3.10.12 Darwin/24.3.0

File hashes

Hashes for oxaigen_auth-0.0.3.tar.gz
Algorithm Hash digest
SHA256 ceb5a9d45134aeffbe9038fff14a40ae6ab0331270e52de2bac7fb23e4c6b38a
MD5 2944059f15f378e08e50a22b907b0a50
BLAKE2b-256 f4490f6e0fc3630157778a6b995f90c87374f63aa4b6df8134afee28a0158a40

See more details on using hashes here.

File details

Details for the file oxaigen_auth-0.0.3-py3-none-any.whl.

File metadata

  • Download URL: oxaigen_auth-0.0.3-py3-none-any.whl
  • Upload date:
  • Size: 21.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.5.1 CPython/3.10.12 Darwin/24.3.0

File hashes

Hashes for oxaigen_auth-0.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 1b9f8211b91379647076300fa614c244de989b03d97497cfef777fbe322d67ad
MD5 4b13db77a90fc26baf06d07f0f4ee90d
BLAKE2b-256 f6227a6f32627028b1c7821ba6ae30a79b992adfc7a7a1d0ac532eba7d991937

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page