Scope-based authorization in Python
A simple Python class that checks user scopes against required permissions for a resource, returning an authorization decision.
Python code
27 linesclass ScopeAuthorization:
def __init__(self):
self.scopes = {
"read": ["resource:read"],
"write": ["resource:read", "resource:write"],
"admin": ["resource:read", "resource:write", "resource:delete"]
}
def authorize(self, user_scopes, required_scope, resource):
if not required_scope in self.scopes:
return f"Unknown scope: {required_scope}"
if not user_scopes or not isinstance(user_scopes, list):
return f"User has no scopes. Required: {required_scope} for {resource}"
if any(scope in self.scopes[required_scope] for scope in user_scopes):
return f"Authorized: {resource} (scope: {required_scope})"
else:
return f"Denied: {resource} (required scope: {required_scope})"
if __name__ == "__main__":
auth = ScopeAuthorization()
print(auth.authorize(["resource:read", "resource:write"], "write", "orders/123"))
print(auth.authorize(["resource:read"], "write", "orders/123"))
print(auth.authorize(["resource:read"], "read", "invoices/456"))
print(auth.authorize([], "read", "reports/789"))
Output
Authorized: orders/123 (scope: write)
Denied: orders/123 (required scope: write)
Authorized: invoices/456 (scope: read)
User has no scopes. Required: read for reports/789
How it works
The ScopeAuthorization class maps named scopes (like read, write, admin) to granular resource permissions. The authorize method first checks if the required scope is valid, then verifies the user has a non-empty list of scopes, and finally checks for any overlap between the user's scopes and the required scope's permissions. This pattern separates permission definitions from enforcement logic, making it easy to adjust access levels without touching business code. It returns descriptive messages for each case, which can be useful for debugging or logging in real applications.
Common mistakes
- Using `required_scope in self.scopes` instead of `not required_scope in self.scopes` for the unknown scope check
- Forgetting to validate that user_scopes is a list before iterating over it
- Assuming admin automatically gets write access if write doesn't include all admin scopes
Variations
- Use a dictionary of dictionaries to define scopes with more granular permissions per resource type
- Implement an `is_authorized` method that returns True/False instead of a message
Real-world use cases
- API gateways that validate JWT claims or OAuth scopes before routing requests to protected endpoints.
- Dashboard applications that show or hide UI elements based on the logged-in user's role permissions.
- Background job schedulers that check if a worker token has the required scope to trigger resource maintenance tasks.
Sponsored
More from API design & gRPC
- Build a Bulk Array POST Mock Server in Python medium
- Build a Mock REST API with PUT and GET in Python medium
- Convert Protobuf to JSON and Dict in Python easy
- Create a Data Helper in Python for gRPC-style APIs easy
- Format data in Python using dataclasses like gRPC messages easy
- Generate an OpenAPI Spec from Mock Routes in Python easy
Keep learning
Related tutorials and quizzes for this topic.