Skip to main content

Security scopes and roles

FastAPI provides several tools to handle Security, Authorization, and Authentication. In this tutorial, we will focus on Security Scopes and Roles. These are critical concepts in managing access controls within your FastAPI application.

Understanding Security Scopes

Security scopes allow you to define permissions or roles in your application. You can think of them as labels that you assign to specific routes, and they indicate what permissions are needed to access those routes.

To define a security scope for a route, you simply add a list of scopes in the Security dependency in your route operation function.

from fastapi import Depends, FastAPI, Security
from fastapi.security import OAuth2PasswordBearer
from fastapi.security.scopes import SecurityScopes

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

app = FastAPI()

@app.get("/items/", response_model=list[Item])
async def read_items(
security_scopes: SecurityScopes,
token: str = Depends(oauth2_scheme),
):
if security_scopes.scopes:
authenticate_value = f"Bearer scope={security_scopes.scope_str}"
ensure_token(token, authenticate_value)
return [{"item": "Foo", "value": 42}]

In the example above, the route /items/ has a security scope of items:read. Only users with this scope can access it.

Understanding Roles

Roles in FastAPI are quite similar to scopes - they can be used to restrict access to specific routes based on the role of a user. A user can have one or more roles, and these roles can be used to allow or deny access to certain routes.

Here's an example of how you can use roles:

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, SecurityScopes

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token", scopes={"items": "Read items"})

app = FastAPI()

def get_current_user(
security_scopes: SecurityScopes,
token: str = Depends(oauth2_scheme)
):
if security_scopes.scopes and security_scopes.scopes[0] not in get_roles(token):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Not enough permissions"
)
return get_user(token)

@app.get("/items/", response_model=list[Item])
async def read_items(user: str = Depends(get_current_user)):
return [{"item": "Foo", "value": 42}]

In the above example, the get_current_user dependency ensures that the user role includes the items:read scope. If the user's roles don't include this scope, a 401 Unauthorized response is returned.

Summary

Scopes and roles are powerful tools provided by FastAPI to manage permissions in your application. By properly using them, you can ensure that only authorized users can access certain routes in your application.

Remember, scopes are defined in the API routes, and roles are defined in the users. The system checks the user's roles against the required scopes of the route to determine if the user is authorized.

This tutorial covers the basic understanding of scopes and roles in FastAPI. You can explore more advanced topics based on this understanding.