Dependencies
All dependencies live in fastapi_simple_tinyauth.helpers and are meant to be
used with FastAPI's Depends. They read the AuthUser that the middleware
stored on request.state.auth_user.
optional_user
Returns the AuthUser when authenticated, or None when the request is
anonymous.
from typing import Annotated
from fastapi import Depends
from fastapi_simple_tinyauth.helpers import optional_user
from fastapi_simple_tinyauth.models import AuthUser
@app.get("/")
async def index(user: Annotated[AuthUser | None, Depends(optional_user)] = None):
return {"authenticated": user is not None}
require_user
Returns the AuthUser, or raises UnauthenticatedError (401) when anonymous.
from typing import Annotated
from fastapi import Depends
from fastapi_simple_tinyauth.helpers import require_user
from fastapi_simple_tinyauth.models import AuthUser
@app.get("/me")
async def me(user: Annotated[AuthUser, Depends(require_user)]):
return {"username": user.username}
Group dependencies
The three group helpers are factories: you call them with the group
requirement and they return a dependency callable. Each returns the AuthUser
on success, raises UnauthenticatedError (401) when anonymous, and
ForbiddenError (403) when the group requirement is not met.
require_group
The user must belong to a single group.
from typing import Annotated
from fastapi import Depends
from fastapi_simple_tinyauth.helpers import require_group
from fastapi_simple_tinyauth.models import AuthUser
@app.get("/admin")
async def admin(user: Annotated[AuthUser, Depends(require_group("admins"))]):
return {"username": user.username}
require_all_groups
The user must belong to every listed group. An empty list imposes no requirement (any authenticated user passes).
from typing import Annotated
from fastapi import Depends
from fastapi_simple_tinyauth.helpers import require_all_groups
from fastapi_simple_tinyauth.models import AuthUser
@app.get("/release")
async def release(user: Annotated[AuthUser, Depends(require_all_groups(["staff", "maintainers"]))]):
return {"username": user.username}
require_any_group
The user must belong to at least one listed group. An empty list can never be
satisfied and always raises ForbiddenError.
from typing import Annotated
from fastapi import Depends
from fastapi_simple_tinyauth.helpers import require_any_group
from fastapi_simple_tinyauth.models import AuthUser
@app.get("/staff")
async def staff(user: Annotated[AuthUser, Depends(require_any_group(["admins", "staff"]))]):
return {"username": user.username}
Route-level enforcement
You can also apply a group dependency without consuming the user in the handler,
using the route's dependencies list:
from fastapi import Depends
from fastapi_simple_tinyauth.helpers import require_group
@app.get("/admin", dependencies=[Depends(require_group("admins"))])
async def admin_area():
return {"ok": True}
The AuthUser object
AuthUser is a frozen dataclass. username is required (an AuthUser always
represents a logged-in user); the rest are optional: email, name, groups
(a tuple[str, ...]), and sub. It also offers:
has_group(group)— membership in one group.has_all_groups(groups)— membership in all listed groups.has_any_group(groups)— membership in at least one listed group.
Using the helpers without FastAPI
Depends is the only FastAPI-specific piece here; the helpers themselves are
plain functions that take a Starlette Request and return an AuthUser (or
raise). In a plain Starlette app you call them directly inside your handler:
from starlette.requests import Request
from starlette.responses import JSONResponse
from fastapi_simple_tinyauth.helpers import require_group, require_user
async def me(request: Request) -> JSONResponse:
user = require_user(request) # no Depends
return JSONResponse({"username": user.username})
async def admin(request: Request) -> JSONResponse:
user = require_group("admins")(request) # the factory returns a callable
return JSONResponse({"username": user.username})
The raised exceptions subclass Starlette's HTTPException, so Starlette renders
them without any extra wiring. See Middleware for how to add
the middleware to a Starlette app.