FastAPI: Fine-Grained Permissions with OAuth2 Scopes

Think of OAuth2 scopes as permissions on a keycard. A token gets you in the building, but scopes like `items:read` or `items:write` define which rooms you can enter. Use them in FastAPI to grant granular access.
WHY IT EXISTS: Authentication confirms who a user is, but not what they are allowed to do. APIs need a way to grant different levels of access to different users or client applications. For example, a third-party app might only need to read public data, while an internal admin tool needs to write it. Scopes provide this mechanism for fine-grained authorization.
THE MENTAL MODEL: OAuth2 scopes are like specific permissions on a digital keycard. When a user logs in, they are issued a token (the keycard). This token contains a list of scopes (the permissions), such as "read_profile" or "write_posts". When the user tries to access an API endpoint, the server checks not only if the keycard is valid but also if it has the specific permission required for that door. A user with only "read_profile" will be denied access to an endpoint that requires "write_posts".
HOW IT WORKS: In FastAPI, you first define your OAuth2 scheme with all available scopes, like scopes = {"me": "Read current user info.", "items": "Read items."}. Then, for each path operation, you use the Security dependency to declare the scopes required for that endpoint, like Security(get_current_user, scopes=["items"]). When a request comes in, FastAPI automatically verifies that the user's token is valid and contains the "items" scope. If the scope is missing, it returns a 403 Forbidden error without you writing any extra logic.
WHEN TO USE IT: Use scopes whenever your API has different user roles or access levels. This is essential for multi-tenant applications, APIs that integrate with third-party clients, or any system where you need to distinguish between read-only access, write access, admin privileges, or user-specific permissions (e.g., a user can only edit their own data).
WHEN NOT TO USE IT: For very simple, internal APIs where all authenticated users have the same level of access, scopes might be overkill. If your only security requirement is to distinguish between authenticated and unauthenticated users, a simple token check without scopes is sufficient. However, adding scopes from the start can make the API more future-proof.
ONE CANONICAL EXAMPLE: An API has an endpoint GET /users/me to fetch the current user's data, which requires a "me" scope. It also has GET /users/ to list all users, which requires an "admin" scope. A regular user's token will be issued with the "me" scope. They can access /users/me, but when they try to access /users/, FastAPI's security dependency will see their token lacks the "admin" scope and automatically block the request.
Read the original → fastapi.tiangolo.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.