FastAPI cookbook · Intermediate

Implement role-based access control in FastAPI

Restrict endpoints by permission and make sure users only access their own resources.

Approach

Map roles to permissions in one place, expose a require(permission) dependency factory for function-level checks, and enforce object-level access by scoping queries to the current user or tenant. Test both: wrong role → 403, other user's resource → 404.

Solution

from enum import StrEnum
from fastapi import Depends, HTTPException


class Perm(StrEnum):
    ORDERS_READ_ALL = "orders:read_all"
    PRODUCTS_WRITE = "products:write"
    USERS_ADMIN = "users:admin"


ROLE_PERMISSIONS: dict[str, set[Perm]] = {
    "customer": set(),
    "support": {Perm.ORDERS_READ_ALL},
    "admin": set(Perm),
}


def require(*perms: Perm):
    async def checker(user: CurrentUser) -> User:
        granted = set().union(*(ROLE_PERMISSIONS.get(r, set()) for r in user.roles))
        if not set(perms) <= granted:
            raise HTTPException(403, "Insufficient permissions")
        return user
    return Depends(checker)


@router.put("/products/{product_id}", dependencies=[require(Perm.PRODUCTS_WRITE)])
async def update_product(product_id: int, body: ProductIn, db: DB): ...


@router.get("/orders/{order_id}")
async def get_order(order_id: int, db: DB, user: CurrentUser) -> OrderOut:
    stmt = select(Order).where(Order.id == order_id)
    if Perm.ORDERS_READ_ALL not in set().union(*(ROLE_PERMISSIONS[r] for r in user.roles)):
        stmt = stmt.where(Order.user_id == user.id)               # object-level scoping
    order = await db.scalar(stmt)
    if order is None:
        raise HTTPException(404, "Order not found")
    return order

Pitfalls

  • Checking roles but forgetting ownership (IDOR).
  • Role checks scattered as string comparisons.
  • Permissions baked into long-lived tokens.

Variations

  • Policy engines (OPA, Cerbos, Oso) or ReBAC (OpenFGA) for complex sharing rules.

Further reading: OWASP Authorization Cheat Sheet

Reference: https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html

More FastAPI recipes