FastAPI: From Basics to Production · Authentication and Security
Permissions, Roles and Object-Level Checks
Authorize actions with role dependencies and ownership checks.
Authentication says who the user is; authorization decides what they can do. Implement role/permission dependencies (require_role("admin")) for function-level checks and object-level checks in services ("does this order belong to this user?"). Scope queries by owner or tenant so data from other users is never loaded, and return 404 for resources users can't see to avoid leaking existence.
from collections.abc import Callable
def require_permission(permission: str) -> Callable:
async def checker(user: CurrentUser) -> User:
if permission not in user.permissions:
raise HTTPException(403, "Insufficient permissions")
return user
return checker
@router.delete("/products/{product_id}", status_code=204)
async def delete_product(product_id: int, db: DB, user: Annotated[User, Depends(require_permission("products:delete"))]):
await products.delete(db, product_id)
@router.get("/orders/{order_id}")
async def get_order(order_id: int, db: DB, user: CurrentUser) -> OrderOut:
order = await db.scalar(select(Order).where(Order.id == order_id, Order.user_id == user.id)) # scoped
if order is None:
raise HTTPException(404, "Order not found")
return order
Common pitfalls
- Checking roles but not ownership (IDOR).
- Authorization only in the frontend.
- Returning 403 for other users' resources, confirming they exist.
Key points
- Role/permission dependencies
- Scope queries by owner/tenant
- Test cross-user access
Further reading: FastAPI: OAuth2 scopes
Practice questions
What's an IDOR and how do you prevent it in FastAPI?
Answer
Insecure Direct Object Reference: accessing another user's resource by changing an ID. Prevent it by scoping queries to the current user/tenant and checking ownership in services.
Why use a dependency factory like require_permission('x')?
Answer
It returns a configured dependency per permission, keeping endpoint signatures declarative and the check reusable and testable.
Open in the app to mark lessons complete, take notes and track your progress.