Authorization Dependencies
OutlabsAuth exposes FastAPI dependencies through auth.deps. They authenticate
the configured credential sources, apply account-state rules, and keep the
authorization decision inside the library.
require_auth(...) or require_permission(...).
The two-phase API later on this page is for infrastructure components that must
authenticate once and authorize several resources in one request.Authenticate a caller
from fastapi import Depends
@app.get("/profile")
async def profile(ctx: dict = Depends(auth.deps.require_auth())):
return {"authenticated": True, "source": ctx["source"]}
require_auth(active=True, verified=False, optional=False) accepts any
configured credential source. Set verified=True when the route requires a
verified user. Set optional=True only when the route deliberately supports an
anonymous result.
The returned dictionary is an auth-owned context, not a public scope format. It is safe to use identity fields for application behavior; do not grant access by interpreting raw permission or scope metadata from it.
Require permissions
@app.get("/reports")
async def read_reports(
ctx: dict = Depends(auth.deps.require_permission("report:read")),
):
return {"authorized": True, "source": ctx["source"]}
@app.post("/reports/export")
async def export_reports(
ctx: dict = Depends(
auth.deps.require_permission(
"report:read",
"report:export",
require_all=True,
)
),
):
...
Multiple permissions mean “any” by default. Pass require_all=True when every
permission is required. Authentication failures return 401; authenticated
callers without the grant receive 403.
Entity and tree checks
EnterpriseRBAC adds context-aware checks:
@app.get("/entities/{entity_id}/billing")
async def entity_billing(
entity_id: UUID,
ctx: dict = Depends(
auth.deps.require_entity_permission(
"billing:read",
entity_id_param="entity_id",
)
),
):
...
@app.get("/entities/{entity_id}/descendants")
async def descendants(
entity_id: UUID,
ctx: dict = Depends(
auth.deps.require_tree_permission(
"entity:read_tree",
"entity_id",
source="path",
)
),
):
...
require_entity_permission resolves the named path parameter and checks inside
that entity. require_tree_permission supports source="path", "query", or
"header"; use the path form when possible because the protected resource is
explicit in the route.
Restrict credential types
@app.post("/webhooks/import")
async def import_webhook(
ctx: dict = Depends(auth.deps.require_source("api_key")),
):
...
@app.post("/system/reindex")
async def reindex(
ctx: dict = Depends(auth.deps.require_superuser()),
):
...
require_source accepts one of the configured backend names such as jwt,
api_key, or service_token. require_superuser authenticates first, then
requires the user’s superuser flag.
Authenticate once, authorize several resources
Added in 0.1.0a26, authorize_authenticated(...) is the supported boundary
for an infrastructure component that authenticates once and then checks several
resources. It does not re-enter a credential backend or record API-key usage a
second time.
ctx = await auth.deps.require_auth()(
request=request,
session=auth_session,
)
if auth.deps.authenticated_authorization_requires_session(ctx):
async with auth.session_factory() as policy_session:
await auth.deps.authorize_authenticated(
request,
ctx,
"queue_a:run",
"queue_b:run",
require_all=True,
session=policy_session,
)
else:
await auth.deps.authorize_authenticated(
request,
ctx,
"queue_a:run",
"queue_b:run",
require_all=True,
)
The session helper is deliberately conservative: user and JWT identities need a policy session; service tokens do not; integration principals may avoid one only when entity traversal and ABAC are not involved. If the component already owns a suitable request-scoped session, it may pass that session directly.
authorize_authenticated(...) also accepts entity_id and
resource_context_provider, matching the entity and ABAC behavior of
require_permission(...). The authenticated context must belong to the same
request; a context copied from another request is rejected.
Choose the right API
| Need | Use |
|---|---|
| Any valid configured credential | require_auth() |
| One or more grants | require_permission(...) |
| A grant inside one entity | require_entity_permission(...) |
| A grant across an entity subtree | require_tree_permission(...) |
| One credential source only | require_source(...) |
| A human superuser | require_superuser() |
| Authenticate once, authorize many resources | authorize_authenticated(...) |