Skip to main content

FastAPI dependency authenticating an Auths-Presentation request into a typed Principal

Project description

auths-fastapi

A FastAPI dependency that authenticates an Auths-Presentation request and yields a typed Principal, or raises HTTPException. It is the Python counterpart of the Axum reference middleware in crates/auths-api/src/rp_auth.rs: an injectable verifier, a real single-use challenge store, a verdict→status mapping, and a dependency that hands a handler a Principal only on success.

Scope

  • First-party only. The relying party trusts credentials issued under DIDs it has pinned in pinned_roots (the .auths/roots model — DID-only; capabilities come from the verified credential, never the request). There is no federation or third-party issuer discovery.
  • Challenge mode is the default. The interactive GET /v1/auth/challenge → single-use nonce → present flow is the v1 path and the one this package mints. A TTL binding is opt-in (non-interactive, no store entry to consume); within its TTL a TTL presentation can be replayed, so prefer the challenge binding unless you have a reason not to.
  • Single process. The bundled ChallengeStore lives in one process's heap. Behind a load balancer fronting N nodes a nonce minted on one node is unknown to another, and the single-use guarantee holds only per node — supply a shared store backend for multi-node.

Security notes

  • The nonce and signature are never logged by this package; do not log the Authorization header in your own middleware either.
  • 401 responses carry WWW-Authenticate: Bearer so generic clients treat them as a standard auth challenge.
  • The expected audience is the relying party's configured audience, not the wire header.

Install

pip install auths-fastapi            # the dependency + challenge store (fake-verifier testable)
pip install "auths-fastapi[native]"  # + the `auths` binding for the production verifier
pip install "auths-fastapi[client]"  # + httpx for fetch_challenge

Usage

from fastapi import Depends, FastAPI
from auths_fastapi import (
    Capability, ChallengeStore, KeriPresentationVerifier, Principal,
    PresentationInputs, auths_principal, challenge_router, configure, configure_mint,
)

AUDIENCE = "api.example.com"
store = ChallengeStore(max_live=10_000)

def load_inputs(credential_said: str) -> PresentationInputs:
    # Resolve the credential SAID to its KEL/TEL inputs from your registry.
    ...

configure(KeriPresentationVerifier(
    audience=AUDIENCE,
    challenges=store,
    load_inputs=load_inputs,
    pinned_roots=frozenset({"did:keri:Eroot"}),
))
configure_mint(store, AUDIENCE)

app = FastAPI()
app.include_router(challenge_router)  # GET /v1/auth/challenge

@app.post("/v1/deploy")
async def deploy(principal: Principal = Depends(auths_principal(Capability("deploy:prod")))):
    return {"deployed_by": principal.subject}

Guard a whole group

from fastapi import APIRouter, Depends

admin = APIRouter(
    prefix="/v1/admin",
    dependencies=[Depends(auths_principal(Capability("admin:read")))],
)

@admin.get("/status")          # protected by the router-level dependency; no Principal needed
async def admin_status():
    return {"status": "ok"}

A route that does not depend on auths_principal(...) receives no Principal and is unauthenticated by construction.

Client flow

from auths_fastapi import fetch_challenge

issued = fetch_challenge("https://api.example.com/v1/auth/challenge")
# sign over issued.nonce, build the Auths-Presentation token, send it in Authorization.

Status mapping

Outcome Status Header
Verified, capability satisfied 200
Missing/malformed header, expired, revoked, wrong audience, replay, holder-not-current, unpinned issuer 401 WWW-Authenticate: Bearer
Authenticated but missing the required capability 403
Challenge store at capacity 503

Testing without the native binding

The crypto verify step is injected behind the PresentationVerifier protocol. Tests supply a fake verifier over the real ChallengeStore, so replay/audience/expiry are genuinely exercised with no binding installed (see tests/test_dependency.py). Run pytest.

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

auths_fastapi-0.1.3.tar.gz (51.5 kB view details)

Uploaded Source

Built Distribution

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

auths_fastapi-0.1.3-py3-none-any.whl (15.1 kB view details)

Uploaded Python 3

File details

Details for the file auths_fastapi-0.1.3.tar.gz.

File metadata

  • Download URL: auths_fastapi-0.1.3.tar.gz
  • Upload date:
  • Size: 51.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for auths_fastapi-0.1.3.tar.gz
Algorithm Hash digest
SHA256 70f9972490a20ddd00f4d0b207f2b26d40ebc6e15240abb2050b00f55a8a7397
MD5 7000b229d8e6edcad2a3a5737273f6a5
BLAKE2b-256 ce643f53f3745300013d33a7354212641763855ded94e9d01de4725c26b39601

See more details on using hashes here.

Provenance

The following attestation bundles were made for auths_fastapi-0.1.3.tar.gz:

Publisher: publish-fastapi.yml on auths-dev/auths

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file auths_fastapi-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: auths_fastapi-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 15.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for auths_fastapi-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 159bd3b06455e463d6ffe229039504418e9d086f306ba3ec299195417142b8d7
MD5 799b8669c7058b0f4cc6febaba207083
BLAKE2b-256 b1e90db0f2d27f65f3bd88c467e5296c1287115bd70721a14ef477f2a1bdfd72

See more details on using hashes here.

Provenance

The following attestation bundles were made for auths_fastapi-0.1.3-py3-none-any.whl:

Publisher: publish-fastapi.yml on auths-dev/auths

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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