middleware.auth

Page actions AI-ready formats and sharing
Open LLM text
Share with AI
Ask Claude Ask ChatGPT Ask Gemini Ask Copilot

Authentication middleware — dual-mode session + token auth.

Authenticates requests via session cookies (browsers) or bearer tokens (API clients). The authenticated user is stored in a ContextVar, accessible viaget_user()from any…

Authentication middleware — dual-mode session + token auth.

Authenticates requests via session cookies (browsers) or bearer tokens (API clients). The authenticated user is stored in a ContextVar, accessible viaget_user()from any handler or middleware.

RequiresSessionMiddlewarefor session-based auth. Token auth works independently.

Usage::

from chirp.middleware.auth import AuthConfig, AuthMiddleware, get_user, login, logout
from chirp.middleware.sessions import SessionConfig, SessionMiddleware

app.add_middleware(SessionMiddleware(SessionConfig(secret_key="...")))
app.add_middleware(AuthMiddleware(AuthConfig(
    load_user=my_load_user,       # async (id: str) -> User | None
    verify_token=my_verify_token, # async (token: str) -> User | None
)))

# In a handler:
user = get_user()
if user.is_authenticated:
    ...

# Login/logout:
await login(user)
await logout()

middleware.auth

Name Type Default Description
type
qualified_name
element_type
description
source_file
line_number
is_autodoc
autodoc_element
_autodoc_template
_autodoc_url_path
_autodoc_page_type
title
doc_content_hash

Symbols on this page

class User

Minimal user protocol.

Any object withid and is_authenticatedsatisfies this. Developers bring their own user model — ORM class, dataclass, etc.

Jump to symbol
class UserWithPermissions

Extended user protocol with permission support.

Used by@requires(*permissions)to check access.

Jump to symbol
class ClientWithScopes

Machine-client protocol with token-scope support.

The machine-auth counterpart toUserWithPermissions: a verify_token-resolved client (webhook / cron / provisioning caller) exposes the token's…

Jump to symbol
class TokenRevocationStore

Protocol for an app-supplied bearer-token revocation backend.

The stateless bearer path (verify_token) has no built-in revocation: once a token verifies, it stays…

Jump to symbol
class AnonymousUser

Sentinel for unauthenticated requests.

Returned byget_user()when no user is authenticated. Eliminates null checks —get_user() never returns None.

Jump to symbol
function _set_stream_user

Re-establish the auth user while a streaming generator drains.

Jump to symbol
function get_user

Return the current authenticated user (orAnonymousUser).

RaisesLookupErrorif called outside a request with AuthMiddlewareactive.

Inside anEventStreamgenerator (SSE), this…

Jump to symbol
function login

Log in a user — regenerate session, set user ID, update ContextVar.

Regenerates the session to prevent session fixation attacks. Call from your login…

Jump to symbol
function logout

Log out the current user — regenerate session + clear ContextVar.

Regenerates the session to discard all session data (not just the user ID).…

Jump to symbol
class AuthConfig

Authentication middleware configuration.

Jump to symbol
function current_user

Return the current user for templates.

Template-friendly alias forget_user(). Returns AnonymousUser if no user is authenticated, never raises.

Registered as a template…

Jump to symbol
class AuthMiddleware

Dual-mode authentication middleware.

Tries token auth first (stateless, for API clients), then falls back to session auth (stateful, for browsers). Sets the authenticated user…

Jump to symbol
alias MachineClient

Alias ofmiddleware.auth.ClientWithScopes

Jump to symbol
User
class

Minimal user protocol.

Any object withid and is_authenticatedsatisfies this. Developers bring their own user model — ORM class, dataclass, etc.

UserWithPermissions
class

Extended user protocol with permission support.

Used by@requires(*permissions)to check access.

ClientWithScopes
class

Machine-client protocol with token-scope support.

The machine-auth counterpart toUserWithPermissions: a verify_token-resolved client (webhook / cron / provisioning caller) exposes the token's scopes so a declarativeAuthSpec(scopes=...)can gate on them independently of human permissions. The scope axis is deliberately separate frompermissions— a machine client need not implement UserWithPermissions, and a human user need not implement this protocol; the shared gate checks each axis only when the activeAuthSpec declares it.

scopes is a frozenset[str] (same shape as permissions). Bring your own client model — any object withid, is_authenticated, and scopessatisfies it. The scope-bearing client flows through _authenticate_token() unchanged.

TokenRevocationStore
class

Protocol for an app-supplied bearer-token revocation backend.

The stateless bearer path (verify_token) has no built-in revocation: once a token verifies, it stays valid until it expires. A revocation store closes that gap — it is consulted afterverify_tokenreturns a user (token branch only) and gives two revocation axes that mirror how session_versiongives the session path mass revocation:

  • per-token:is_token_revoked() rejects a single revoked jti;
  • per-user cutoff:user_revoked_at() rejects every token a user was issued before arevoked_at timestamp (token iat <= revoked_at).

Both axes require token claims, which Chirp does not decode itself — supply token_claims to surface {jti, sub, iat}from the opaque token. Withtoken_claims unset, only is_token_revoked() can run (and only if the store is reachable without ajti); the cutoff axis is skipped.

The store is app-supplied and async. Chirp holds no lock — the store is responsible for its own concurrency (mirrorsSessionStore). On a store error Chirp fails open (treats the token as not revoked) and emits anauth.token.revocation_check_errorsecurity event, so a backend blip does not 401 every API client.

AnonymousUser
class

Sentinel for unauthenticated requests.

Returned byget_user()when no user is authenticated. Eliminates null checks —get_user() never returns None.

_set_stream_user
function
def _set_stream_user(user: User) -> Token[User]

Re-establish the auth user while a streaming generator drains.

Parameters

Name Type Default Description
user User
get_user
function
def get_user() -> User

Return the current authenticated user (orAnonymousUser).

RaisesLookupErrorif called outside a request with AuthMiddlewareactive.

Inside anEventStreamgenerator (SSE), this returns the user captured at connect time. SSE identity is pinned for the connection's lifetime: a user logged out or permission-revoked mid-stream keeps the connect-time identity until they reconnect. Callkick_user() to terminate that user's live streams so htmx reconnect re-runs auth middleware and re-pins fresh permissions. An unauthenticated connection sees AnonymousUserfor the whole stream.

No parameters.

login
function
def login(user: User) -> None

Log in a user — regenerate session, set user ID, update ContextVar.

Regenerates the session to prevent session fixation attacks. Call from your login handler after verifying credentials::

user = await verify_credentials(email, password)
if user:
    login(user)
    return Redirect("/dashboard")

RequiresSessionMiddleware and AuthMiddlewareto be active.

Parameters

Name Type Default Description
user User
logout
function
def logout() -> None

Log out the current user — regenerate session + clear ContextVar.

Regenerates the session to discard all session data (not just the user ID). Call from your logout handler::

logout()
return Redirect("/")

RequiresSessionMiddleware and AuthMiddlewareto be active.

No parameters.

AuthConfig
class

Authentication middleware configuration.

current_user
function
def current_user() -> User

Return the current user for templates.

Template-friendly alias forget_user(). Returns AnonymousUser if no user is authenticated, never raises.

Registered as a template global whenAuthMiddlewareis active::

{% if current_user().is_authenticated %}
    <a href="/profile">{{ current_user().name }}</a>
{% else %}
    <a href="/login">Sign in</a>
{% endif %}

Inside anEventStreamgenerator (SSE), this returns the user captured at connect time — seeget_user() for the pinned-identity semantics.

No parameters.

AuthMiddleware
class

Dual-mode authentication middleware.

Tries token auth first (stateless, for API clients), then falls back to session auth (stateful, for browsers). Sets the authenticated user in a ContextVar accessible viaget_user().

Middleware ordering::

app.add_middleware(SessionMiddleware(...))  # 1st: sessions
app.add_middleware(AuthMiddleware(...))      # 2nd: auth
app.add_middleware(CSRFMiddleware())         # 3rd: CSRF

Usage::

from chirp.middleware.auth import AuthConfig, AuthMiddleware

app.add_middleware(AuthMiddleware(AuthConfig(
    load_user=db.get_user_by_id,
    verify_token=db.get_user_by_token,
)))
MachineClient
alias

Alias ofmiddleware.auth.ClientWithScopes

View source · /home/runner/work/chirp/chirp/site/../src/chirp/middleware/auth.py:1