Skip to main content

SPNEGO / Kerberos (HTTP Negotiate) authentication provider for FastAPI and Starlette

Project description

fastapi-spnego

SPNEGO / Kerberos (HTTP Negotiate) authentication for FastAPI and Starlette.

The one enterprise auth mechanism with no FastAPI library — until now. Where fastapi-ldap covers LDAP and Authlib covers OAuth2/OIDC, Kerberos/SPNEGO users have been told to bolt on Keycloak. This package fills that gap: a small, framework-idiomatic Negotiate provider you drop in as a dependency.

Status: alpha. The dependency, the optional ASGI middleware, and credential delegation are implemented and covered by unit tests. The real GSSAPI path is proven end-to-end against a containerized MIT KDC (docker compose run --rm test) — genuine kinit + Negotiate handshake, mutual auth, and delegation.

Install

pip install fastapi-spnego[gssapi]   # Linux/macOS; needs libkrb5-dev

Platform support: the server-side GSSAPI backend runs on Linux and macOS (where FastAPI is almost always deployed). Windows clients authenticate normally against it. A Windows/SSPI server backend is on the roadmap. The base package is pure-Python and imports anywhere; the gssapi extra is what requires system Kerberos libraries.

Use

from fastapi import Depends, FastAPI
from fastapi_spnego import SpnegoAuth, SpnegoIdentity

app = FastAPI()
spnego = SpnegoAuth()

@app.get("/whoami")
def whoami(identity: SpnegoIdentity = Depends(spnego)):
    return {"user": identity.username, "realm": identity.realm}

Configure via SPNEGO_ env vars (see fastapi_spnego/config.py):

export SPNEGO_HOSTNAME=app.example.com   # FQDN of the service principal
export SPNEGO_KEYTAB=/etc/app.keytab     # HTTP/app.example.com@REALM
export SPNEGO_ALLOW_DELEGATION=true      # capture forwarded client TGTs (optional)

A bad or missing token is handled for you: no credentials → 401 with a WWW-Authenticate: Negotiate challenge; an invalid token → 403 (never a 500). Set SPNEGO_AUTO_ERROR=false for optional auth, where the dependency returns None instead of challenging.

Global middleware (alternative)

Prefer the Depends() above for most apps. If you'd rather apply Negotiate globally and read the identity off request.state (Flask before_request style), use the middleware:

from fastapi import FastAPI, Request
from fastapi_spnego import SpnegoMiddleware

app = FastAPI()
app.add_middleware(SpnegoMiddleware, exclude_paths=["/health", "/metrics"])

@app.get("/whoami")
def whoami(request: Request):
    identity = request.state.spnego_identity
    return {"user": identity.username}

Credential delegation

With SPNEGO_ALLOW_DELEGATION=true, when a client forwards (delegates) its TGT the server stores it in a per-user credentials cache and exposes the handle on the identity, so your app can act onward as that user:

identity.delegated_ccache   # e.g. "FILE:/tmp/fastapi_spnego_ccache/cache_alice_EXAMPLE.COM"
# use it: env KRB5CCNAME=<handle> for an onward Kerberos connection

Requires the SPN to be flagged trusted for delegation and the client to opt in (GSSAPI/SSPI-only; the GSSAPI backend supports this, pyspnego will not).

Design

  • A Depends(), not a global. Fits FastAPI's DI model; trivial to override in tests.
  • Pluggable backend. GSSAPI first (Linux/macOS, supports credential delegation); a pyspnego backend for Windows/SSPI is on the roadmap.
  • Non-blocking. GSSAPI calls run in a threadpool.
  • Just a provider. Returns a verified principal; your app owns users/sessions/RBAC.

Requirements were distilled from pgAdmin's production Kerberos implementation.

Development

This project uses uv for environment and dependency management.

uv sync                 # create .venv + install the base dev group
uv run pytest           # run the test suite
uv run ruff check .     # lint
uv run ruff format .    # format
uv run mypy fastapi_spnego

The base dev group is pure-Python and installs anywhere. To run the integration tests that exercise the real GSSAPI backend you also need the gssapi group, which requires system Kerberos headers (krb5-config on PATH, e.g. apt install libkrb5-dev):

uv sync --group gssapi

uv.lock is committed for reproducible dev/CI environments. It does not affect consumers, who install the published package via pip as usual.

End-to-end test against a real KDC

The unit tests use a fake backend and need no Kerberos. The real proof — an actual kinit + Negotiate handshake against the GSSAPI backend — runs in Docker, which stands up a throwaway MIT KDC, the app, and a client:

docker compose run --rm --build test   # KDC + app + integration suite
docker compose up --build app           # or: just serve on localhost:8000

This exercises the challenge, a successful handshake with mutual auth, and credential delegation. See docker-compose.yml and docker/.

License

MIT.

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

fastapi_spnego-0.1.0.tar.gz (17.5 kB view details)

Uploaded Source

Built Distribution

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

fastapi_spnego-0.1.0-py3-none-any.whl (16.0 kB view details)

Uploaded Python 3

File details

Details for the file fastapi_spnego-0.1.0.tar.gz.

File metadata

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

File hashes

Hashes for fastapi_spnego-0.1.0.tar.gz
Algorithm Hash digest
SHA256 7961909a2b0a81caade341e3a6fc1f36de1a69812873ea8d5623cb20caab8992
MD5 ef63d31d4bed6582e32d3dc10692370a
BLAKE2b-256 7cac64204eeac85f553f449ed359208668761a3f0e094eb69bf788dd0b7ef435

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastapi_spnego-0.1.0.tar.gz:

Publisher: publish.yml on gvozdetsky/fastapi-spnego

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

File details

Details for the file fastapi_spnego-0.1.0-py3-none-any.whl.

File metadata

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

File hashes

Hashes for fastapi_spnego-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5ee7db095248fe71ac4614d2a2e4a7cb79fa078488bd93e7616a2358047f7cf3
MD5 5808b42df70bf71e0da3812dd3cb5294
BLAKE2b-256 deade6a3510ee96b1848d9ffffecd31392df6786a7b2213813e2353efeabd66a

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastapi_spnego-0.1.0-py3-none-any.whl:

Publisher: publish.yml on gvozdetsky/fastapi-spnego

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