Permissions
This integration exposes field extensions to use Djangoβs Permission System for checking permissions on GraphQL fields.
It supports protecting any field for cases like:
- The user is authenticated
- The user is a superuser
- The user or a group they belong to has a given permission
- The user or the group they belong to has a given permission to the resolved value
- The user or the group they belong to has a given permission to the parent of the field
- etc
How it works
Loading graph...
graph TD A[Extension Check for Permissions] --> B; B[User Passes Checks] -->|Yes| BF[Return Resolved Value]; B -->|No| C; C[Can return 'OperationInfo'?] -->|Yes| CF[Return 'OperationInfo']; C -->|No| D; D[Field is Optional] -->|Yes| DF[Return 'None']; D -->|No| E; E[Field is a 'List'] -->|Yes| EF[Return an empty 'List']; E -->|No| F; F[Field is a relay 'Connection'] -->|Yes| FF[Return an empty relay 'Connection']; F -->|No| GF[Raises 'PermissionDenied' error];
Basic Example
import strawberry_djangofrom strawberry_django.permissions import ( IsAuthenticated, HasPerm, HasSourcePerm, HasRetvalPerm,)
@strawberry_django.typeclass SomeType: login_required_field: RetType = strawberry_django.field( # will check if the user is authenticated extensions=[IsAuthenticated()], ) perm_required_field: OtherType = strawberry_django.field( # will check if the user has `"some_app.some_perm"` permission extensions=[HasPerm("some_app.some_perm")], ) obj_perm_required_field: OtherType = strawberry_django.field( # will check the permission for the resolved value extensions=[HasRetvalPerm("some_app.some_perm")], ) Available Permission Extensions
IsAuthenticated
Checks if the user is authenticated and active.
from strawberry_django.permissions import IsAuthenticated
@strawberry_django.field(extensions=[IsAuthenticated()])def protected_field(self) -> str: return "secret" Parameters:
-
message: str- Custom error message (default: βUser is not authenticated.β) -
fail_silently: bool- IfTrue, returnNone/empty instead of raising error (default:True)
IsStaff
Checks if the user is a staff member (user.is_staff ).
from strawberry_django.permissions import IsStaff
@strawberry_django.field(extensions=[IsStaff()])def admin_field(self) -> str: return "admin only" Parameters:
-
message: str- Custom error message (default: βUser is not a staff member.β) -
fail_silently: bool- IfTrue, returnNone/empty instead of raising error (default:True)
IsSuperuser
Checks if the user is a superuser (user.is_superuser ).
from strawberry_django.permissions import IsSuperuser
@strawberry_django.field(extensions=[IsSuperuser()])def superuser_field(self) -> str: return "superuser only" Parameters:
-
message: str- Custom error message (default: βUser is not a superuser.β) -
fail_silently: bool- IfTrue, returnNone/empty instead of raising error (default:True)
HasPerm
Checks if the user has global (model-level) permissions.
from strawberry_django.permissions import HasPerm
@strawberry_django.field(extensions=[HasPerm("app.add_model")])def create_something(self) -> Model: ... Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
perms | str | list[str] | required | Permission(s) to check (e.g., "app.permission" ) |
any_perm | bool | True | If True , user needs ANY of the perms; if False , needs ALL |
with_anonymous | bool | True | If True , anonymous users automatically fail (optimization) |
with_superuser | bool | False | If True , superusers bypass permission checks |
message | str | "You don't have permission..." | Custom error message |
fail_silently | bool | True | If True , return None /empty instead of raising error |
Examples:
# Require ALL permissions@strawberry_django.field( extensions=[HasPerm(["app.view_model", "app.change_model"], any_perm=False)])def sensitive_field(self) -> str: ...
# Allow superusers to bypass@strawberry_django.field( extensions=[HasPerm("app.special_permission", with_superuser=True)])def special_field(self) -> str: ...
# Raise error instead of returning None@strawberry_django.field( extensions=[HasPerm("app.required_permission", fail_silently=False)])def required_field(self) -> str: ... HasSourcePerm
Checks if the user has permission for the parent/source object of the field.
This is useful when you want to check permissions on the object that contains the field, not the fieldβs return value.
from strawberry_django.permissions import HasSourcePerm
@strawberry_django.type(models.Document)class DocumentType: id: auto title: auto
# Only show content if user has view permission on THIS document @strawberry_django.field(extensions=[HasSourcePerm("documents.view_document")]) def content(self) -> str: return self.content Parameters: Same as HasPerm
HasRetvalPerm
Checks if the user has permission for the resolved/returned value.
This is useful for:
- Checking object-level permissions on query results
- Filtering lists to only include objects the user can access
from strawberry_django.permissions import HasRetvalPerm
@strawberry.typeclass Query: # Returns only documents the user has permission to view @strawberry_django.field(extensions=[HasRetvalPerm("documents.view_document")]) def documents(self) -> list[DocumentType]: return models.Document.objects.all()
# Returns document only if user has permission, else None @strawberry_django.field(extensions=[HasRetvalPerm("documents.view_document")]) def document(self, id: int) -> DocumentType | None: return models.Document.objects.get(pk=id) Parameters: Same as HasPerm
List Filtering: When used on a field returning a list, HasRetvalPerm automatically filters out objects the user doesnβt have permission for, rather than failing the entire query.
Object-Level Permissions
HasSourcePerm and HasRetvalPerm require an authentication backend that supports object permissions. This library works out of the box with django-guardian .
See the django-guardian integration for setup instructions.
No Permission Handling
When permission checks fail, the following is returned (in priority order):
-
OperationInfo/OperationMessageif those types are allowed in the return type -
nullif the field is optional (e.g.,Stringor[String]) - An empty list if the field is a list (e.g.,
[String]!) - An empty
Connectionif the return type is a relay connection - Otherwise, a
PermissionDeniederror is raised
To always raise an error instead, set fail_silently=False :
@strawberry_django.field( extensions=[IsAuthenticated(fail_silently=False)])def must_be_authenticated(self) -> str: ... Combining Multiple Permissions
You can apply multiple permission extensions to a single field:
@strawberry_django.field( extensions=[ IsAuthenticated(), HasPerm("app.special_permission"), ])def protected_field(self) -> str: ... All extensions must pass for the field to resolve.
Custom Error Messages
All permission extensions accept a message parameter:
@strawberry_django.field( extensions=[ IsAuthenticated(message="Please log in to view this content"), HasPerm("premium.access", message="This requires a premium subscription"), ])def premium_content(self) -> str: ... Custom Permission Extensions
Create custom permission logic by subclassing DjangoPermissionExtension :
from strawberry_django.permissions import DjangoPermissionExtension, DjangoNoPermission
class IsVerifiedEmail(DjangoPermissionExtension): DEFAULT_ERROR_MESSAGE = "Email verification required."
def resolve_for_user( self, resolver, user, *, info, source, ): if not user or not user.is_authenticated: raise DjangoNoPermission
if not getattr(user, 'email_verified', False): raise DjangoNoPermission
return resolver() Usage:
@strawberry_django.field(extensions=[IsVerifiedEmail()])def verified_only_field(self) -> str: ... Schema Directives
Permission extensions automatically add schema directives to your GraphQL schema, making permissions visible in introspection. This can be turned off:
@strawberry_django.field( extensions=[HasPerm("app.permission", use_directives=False)])def field_without_directive(self) -> str: ... See Also
- django-guardian Integration - Object-level permissions
- Authentication - User authentication
- Error Handling - Handling permission errors