Skip to content

Middleware

TinyauthMiddleware is a pure-ASGI middleware. Add it to your app with a TinyauthConfig:

from fastapi import FastAPI

from fastapi_simple_tinyauth.config import TinyauthConfig
from fastapi_simple_tinyauth.middleware import TinyauthMiddleware

config = TinyauthConfig(trusted_proxies=["127.0.0.1/32", "::1/128"])

app = FastAPI()
app.add_middleware(TinyauthMiddleware, config=config)

What it does

On each HTTP request:

  • It reads the immediate TCP peer (request.client.host) and checks it against the configured trusted-proxy networks.
  • If the peer is not trusted, it responds with a plain-text HTTP 403 and never calls your app. The forwarded headers are ignored.
  • If the peer is trusted, it parses the identity headers into an AuthUser and stores it on request.state.auth_user.

Non-HTTP scopes (WebSocket, lifespan) pass straight through untouched.

FastAPI or plain Starlette

TinyauthMiddleware is a pure-ASGI middleware and the core package imports only starlette — nothing in src/ imports FastAPI. So it works the same in a plain Starlette app; only the wiring syntax differs:

from starlette.applications import Starlette
from starlette.middleware import Middleware

from fastapi_simple_tinyauth.config import TinyauthConfig
from fastapi_simple_tinyauth.middleware import TinyauthMiddleware

config = TinyauthConfig(trusted_proxies=["127.0.0.1/32", "::1/128"])

app = Starlette(middleware=[Middleware(TinyauthMiddleware, config=config)])

Inside your handlers, call the dependencies directly with the Request instead of using FastAPI's Depends.

The stored user

After the middleware runs, request.state.auth_user is always present:

  • An AuthUser when Remote-User is present.
  • None when it is absent (anonymous request).

You normally do not read request.state.auth_user directly — use the dependencies instead — but it is available if you need it in your own middleware.

Header parsing details

  • Each header value is stripped of surrounding whitespace; an empty value becomes None.
  • The groups header is split on commas, each item is trimmed, and empty items are dropped. " a , ,b " becomes ("a", "b").

The untrusted-proxy response

The 403 for an untrusted peer is emitted directly by the middleware, so it does not pass through your app's exception handlers (the request never reached the app). If you want a custom response shape for it, enforce the proxy check elsewhere too, or handle UntrustedProxyError where you raise it yourself. See Exceptions.