Developers guide

Python Integration

Authdog’s Python integration is currently unreleased and source-only. authdog-fastapi is not available on PyPI, so do not use pip install authdog-fastapi or present the package as a published dependency. Repository documentation points to source in the public authdog/web-sdk repository under packages/python, versioned 0.1.0, with bindings for FastAPI, Django, Flask, Starlette, and aiohttp.

Prerequisites

  • Python 3.10 or newer.
  • An Authdog environment and its publishable public key (pk_...).
  • A pinned commit or reviewed source snapshot from packages/python.
  • A frontend or client that obtains a session for the same Authdog environment.
  • A deployment process willing to consume unreleased source and track upstream changes explicitly.

The source package declares httpx as its base runtime dependency. Repository documentation records framework extras and minimum versions for FastAPI 0.110, Django 4.2, Flask 3.0, Starlette 0.37, and aiohttp 3.9. Published compatibility is not yet guaranteed.

Review and pin source before adopting it. Do not depend on an unpinned branch for production. Because no PyPI release exists, normal registry version resolution, release notes, and package provenance checks are not available.

Implementation

Each framework module exports an Authdog binding. Construct one instance with the environment public key:

import os
from authdog.fastapi import Authdog

authdog = Authdog(public_key=os.environ["PK_AUTHDOG"])

The documented Python core reads authdog-session first, then an Authorization: Bearer <token> header. It resolves identity through the environment’s OIDC userinfo endpoint and returns an AuthdogContext containing token, user, is_authenticated, and user_info.

For FastAPI, use session when anonymous and authenticated responses are both valid:

from fastapi import Depends, FastAPI

app = FastAPI()

@app.get("/")
async def index(ctx=Depends(authdog.session)):
    return {"authenticated": ctx.is_authenticated}

Use require_auth as the actual authentication gate:

@app.get("/me")
async def me(user=Depends(authdog.require_auth)):
    return user

Repository documentation states that missing, invalid, or failed userinfo requests produce anonymous context rather than authenticating the request. Only a successful response with a user sets is_authenticated. require_auth rejects unauthenticated requests with 401.

Equivalent documented framework shapes are:

  • Django: authdog.session(request) and @authdog.require_auth
  • Flask: authdog.session() and @authdog.require_auth
  • Starlette: await authdog.session(request) and await authdog.require_auth(request)
  • aiohttp: await authdog.session(request) and @authdog.require_auth

Logout helpers clear the local cookie and redirect according to framework conventions. Repository documentation warns that logout does not revoke bearer tokens or end an upstream provider session.

Security considerations

Session resolution is informational; require_auth is the enforcement boundary. Every protected route must invoke the framework’s documented gate.

Authentication answers who is calling, not what that caller may do. Apply role, permission, tenant, organization, and resource-ownership checks after require_auth. Return 401 for missing or invalid authentication and 403 for an authenticated caller lacking permission.

Do not use fetch_user=False as authentication. The documented behavior exposes an unverified token while leaving user unset and is_authenticated false. Built-in gates reject that context. Use the option only if a separate trusted validator fully replaces the built-in validation path.

Keep the public key in configuration so environments remain explicit. Although it is publishable, hard-coding it makes development and production mix-ups easier. The source validates key format and restricts identity hosts; custom self-hosted identity locations require explicit allowed-host configuration.

Treat cookies and bearer tokens as credentials. Avoid logging them. Validate each protected request rather than trusting frontend state.

The detailed Python authentication and Python access control pages cover the intended session, gate, logout, role, permission, and ownership patterns. Their installation guidance treats the package as source-only.

Validation checklist

  • Python runtime is 3.10 or newer.
  • Integration source is reviewed and pinned to a commit.
  • No deployment step expects authdog-fastapi from PyPI.
  • Public key belongs to the same environment as client sessions.
  • Anonymous route returns is_authenticated == False for missing or invalid tokens.
  • Protected route returns 401 without a validated user.
  • Authorization failure returns 403 after authentication.
  • fetch_user=False is not treated as validation.
  • Logs redact cookies and bearer tokens.
  • Logout behavior is tested without assuming token revocation.

Troubleshooting

If dependency resolution cannot find authdog-fastapi, that is expected: no PyPI release exists. Confirm the build uses the reviewed source snapshot rather than a registry package name.

If every request is anonymous, verify the client sends authdog-session or a bearer header and that client and backend use the same Authdog environment. Then inspect userinfo reachability and identity-host restrictions.

If a route resolves context but remains publicly accessible, replace informational session use with require_auth at that route’s enforcement point.

If fetch_user=False exposes a token but authentication remains false, that is documented behavior, not a bug.

Next steps

  • Review Python authentication for source installation and session enforcement.
  • Review Python access control, verifying claim names against your environment.
  • Read Backend requests for the shared validation model.
  • Track the source repository for an actual authdog-fastapi release before switching to registry installation.