OutlabsAuth
Auth

ABAC

Attribute conditions on roles and permissions.
Opt-in attribute conditions on top of RBAC.

ABAC adds conditions (attribute + operator + value) to roles and/or permissions. At check time, RBAC must still grant the permission and conditions must pass against a context (user, resource, env, time).


Enable

SurfaceBehavior
EnterpriseRBAC(..., enable_abac=True)Opt-in; default False
OutlabsAuth / AuthConfig.enable_abacSame flag
SimpleRBACForced off
auth = EnterpriseRBAC(
    database_url=...,
    secret_key=...,
    enable_abac=True,
    # Prefer server-derived context; keep this False unless you know why:
    # trust_resource_context_header=False,
)
auth.instrument_fastapi(app, include_resource_context=True)  # when using request-state merge

Do not trust client X-Resource-Context unless you set trust_resource_context_header=True. Prefer a resource_context_provider that loads attributes from your DB.


Where conditions attach

Same shape on both catalogs (25):

Attach pointPathsAuth
Permission/v1/permissions/{id}/condition-groups + /conditionspermission:read / permission:update
Role/v1/roles/{id}/condition-groups + /conditionsrole:read / role:update

Group: operator AND | OR, optional description.
Condition: attribute (dot path, e.g. resource.status), operator (equals, in, matches, …), value, value_type (string | integer | float | boolean | list).

Evaluation shape: ungrouped conditions AND together; within a group use the group operator; groups AND together. Empty conditions → RBAC-only for that attach point.


Evaluation at check time

auth.deps.require_permission(..., resource_context_provider=...) builds a context, then PermissionService.check_permission(..., resource_context=...).

When ABAC is on and condition rows exist: for each candidate grant, role conditions must pass, then at least one matching permission’s conditions must pass. Superusers short-circuit before ABAC. If the flag is on but no conditions exist, the cheaper non-ABAC path runs.


Example: abac_cookbook

Editors may document:update only when resource.status is draft orreview, using a server-derived context (client cannot forge status).

Terminal
cd examples/abac_cookbook
uv run python reset_test_env.py
uv run uvicorn main:app --host 127.0.0.1 --port 8005
uv run python ../../scripts/smoke_abac_cookbook.py

Smoke: configure permission conditions as admin → editor updates draft (200) / published (403).


Caveats

  • Not a row-level ACL product — your host loads resource attributes and passes them via resource_context / provider.
  • Principal / system API keys are RBAC-only: if ABAC is on and the required permission has conditions, those keys are denied — see API Key Host Integration.
  • ABAC can disable some permission-cache fast paths; keep conditions focused.
  • Client resource-context headers stay off by default on purpose.