Scope-Based Authorization and Role Guards
Enforce per-endpoint permissions using OAuth2 scopes and reusable dependency guards for role-based access control.
Authentication vs Authorization
Once a user proves who they are (authentication), you still need to decide what they are allowed to do. That second step is authorization.
- Authentication answers: who are you? (verify the JWT)
- Authorization answers: are you permitted to call this endpoint?
In OAuth2, fine-grained permissions are expressed as scopes — short strings like items:read or users:write. Each token carries the scopes that were granted, and each endpoint declares the scopes it requires.
What a Scope Looks Like
A scope is just a label for a permission. By convention they use a resource:action shape, which keeps them readable as your API grows.
items:read— list or fetch itemsitems:write— create or update itemsadmin— full administrative access
The JWT stores granted scopes, usually as a space-separated string in a scopes claim. Here is a tiny helper that parses and checks them.
def has_scope(token_scopes: str, required: str) -> bool:
granted = token_scopes.split()
return required in granted
claim = "items:read items:write"
print(has_scope(claim, "items:read")) # True
print(has_scope(claim, "admin")) # FalseAll lessons in this course
- OAuth2 Password Flow and Token Issuance
- Signing and Verifying JWTs with python-jose
- Refresh Tokens and Token Rotation
- Scope-Based Authorization and Role Guards