Bob Belderbos: Database-Driven RBAC with FastAPI and Azure Entra ID
This project implements a FastAPI service with granular role-based access control (RBAC) using Azure Entra ID for authentication. Instead of hardcoding access policies into each route, these policies are stored in a database table. This allows administrators to change user permissions without modifying and redeploying the application code. The system uses Azure Entra ID to authenticate users and retrieve their roles from JWT claims. A mapping of endpoint keys to required roles is stored in an EndpointPermission SQLModel table.The core of the authorization logic lies in a require function, which is used as a FastAPI dependency. This function retrieves the required roles for an endpoint from the database and checks if the authenticated user possesses any of them. If not, a 403 Forbidden error is raised. The key string for an endpoint is the only literal hardcoded in its route definition.Critically, the endpoint for managing these permissions is itself protected by the same RBAC mechanism, ensuring only administrators can modify access rules. Safeguards prevent administrators from accidentally revoking their own access to the permission management endpoint and ensure that role assignments are never empty. The article highlights two common Azure configuration issues: using v1 tokens instead of v2, which causes invalid token errors, and the fact that nested group memberships are not reflected in user roles for direct assignment.The project also provides guidance on testing the authorization logic effectively. Tests can override the authentication and session dependencies to use fake users and in-memory SQLite databases, allowing for comprehensive testing without external dependencies. This design, by externalizing policy as data, makes authorization dynamic and manageable, aligning with the 12-factor app principle. The author emphasizes distinguishing between code logic and changeable policy.
EndpointPermissionSQLModel table.The core of the authorization logic lies in arequirefunction, which is used as a FastAPI dependency. This function retrieves the required roles for an endpoint from the database and checks if the authenticated user possesses any of them. If not, a 403 Forbidden error is raised. The key string for an endpoint is the only literal hardcoded in its route definition.Critically, the endpoint for managing these permissions is itself protected by the same RBAC mechanism, ensuring only administrators can modify access rules. Safeguards prevent administrators from accidentally revoking their own access to the permission management endpoint and ensure that role assignments are never empty. The article highlights two common Azure configuration issues: using v1 tokens instead of v2, which causes invalid token errors, and the fact that nested group memberships are not reflected in user roles for direct assignment.The project also provides guidance on testing the authorization logic effectively. Tests can override the authentication and session dependencies to use fake users and in-memory SQLite databases, allowing for comprehensive testing without external dependencies. This design, by externalizing policy as data, makes authorization dynamic and manageable, aligning with the 12-factor app principle. The author emphasizes distinguishing between code logic and changeable policy.