Role Definition Syntax (@Auth)
Relevant source files
The following files were used as context for generating this wiki page:
Role Definition Syntax (@Auth) provides a declarative way to define authorization rules directly within Prisma schema files. By using triple-slash comments (///), developers annotate models and fields to specify which roles can perform specific operations. This approach moves authorization logic from imperative GraphQL resolvers to a centralized, declarative model level, reducing the risk of security vulnerabilities in automatically exposed schemas.
The system uses a custom PEG.js-based parser to interpret these annotations and convert them into structured role descriptions. These descriptions are then consumed by middleware to enforce access control during runtime query execution.
Sources: README.md:1-25, src/descriptionToRoles.ts:16-25
Annotation Structure
The @Auth annotation follows a specific structured format containing operations, roles, and optional arguments. The parser recognizes annotations starting with the @Auth( prefix and ending with a closing parenthesis ).
Syntax Levels
Authorization can be applied at two primary levels within the Prisma schema:
- Model Level: Defines access for the entire entity.
- Field Level: Restricts access to specific fields within a model, even if the model itself is accessible.
Sources: README.md:32-45, src/makeFieldConstraintMiddleware.ts:12-20
Syntax Components
| Component | Description | Example |
|---|---|---|
| Operation | The action being restricted (e.g., read, create, update, delete). | read: |
| Role List | An array of roles allowed to perform the operation. | [Owner, Admin] |
| Role Arguments | Arbitrary key-value pairs passed to the role matcher. | Owner(privileges: [x,y]) |
Sources: src/generated/parser.ts:360-390, src/descriptionToRoles.test.ts:10-45
Grammar and Parsing
The project utilizes a generated parser to transform string-based comments into a RoleDescription object. The parser handles whitespace, comma-separated lists, and nested argument structures.
The diagram shows the transformation flow from a raw Prisma comment to a structured data format used by the middleware.
Sources: src/generated/parser.ts:340-355, src/descriptionToRoles.ts:16-25
Supported Operations
The parser explicitly recognizes four standard CRUD operations:
readcreateupdatedelete
Sources: src/generated/parser.ts:400-415
Role Arguments
Roles can accept complex arguments that influence the behavior of the matcher and queryConstraint functions defined in the global configuration. Arguments support strings and arrays of strings.
Argument Parsing Logic
- Key-Value Pairs: Arguments are defined as
key: value. - Arrays: Multiple values can be enclosed in square brackets
[val1, val2]. - Special Characters: Identifiers support alphanumeric characters, hyphens, and colons.
Sources: src/generated/parser.ts:500-550, src/descriptionToRoles.test.ts:33-45
// Example of parsed output for: @Auth(read:[ User(type:some-type) ])
{
read: [
{
name: 'User',
args: {
type: 'some-type',
},
},
]
}
Sources: src/descriptionToRoles.test.ts:36-45
Implementation in Middleware
Middlewares extract these annotations from the GraphQL info object and the Prisma model metadata.
Field-Level Enforcement
The makeFieldConstraintMiddleware retrieves the description from the parent type's field metadata. If the annotation contains roles, the middleware iterates through them and executes the corresponding roleMatcher. If no roles are granted, the response is patched (e.g., returning null or an empty array).
Sources: src/makeFieldConstraintMiddleware.ts:28-56
Type-Level Enforcement
The makeTypeConstraintMiddleware enforces authorization on relation fields. It extracts the type name from the return type and retrieves the @Auth description from the model definition in the schema.
The sequence diagram illustrates how the middleware uses parsed role definitions to grant or deny access during a request.
Sources: src/makeFieldConstraintMiddleware.ts:43-56, src/makeTypeConstraintMiddleware.ts:56-70
Configuration Interface
The roles defined in the syntax must match the keys provided in the Configuration object passed to the middleware generator.
| Interface Property | Type | Purpose |
|---|---|---|
rolesPerType | RolesPerType | Defines matchers and constraints for roles specific to a Prisma model. |
globalRoles | Record<string, Role> | Defines roles applicable across all models. |
defaultFields | Record<string, any> | Specifies fields to be automatically selected when specific criteria are met. |
Sources: src/index.ts:16-35
Summary
The Role Definition Syntax (@Auth) enables a "security-by-default" posture by allowing developers to declare access rules directly on the data model. By leveraging a PEG.js parser, the system provides a flexible language for expressing complex role requirements, including parameterization, which the middleware layers then enforce consistently across GraphQL queries and Prisma operations.
Sources: README.md:1-15, src/index.ts:50-55