Middleware Configuration Reference
Relevant source files
The following files were used as context for generating this wiki page:
The @joindeed/prisma-auth library provides declarative authorization for Prisma at the model level rather than the GraphQL resolver level. This middleware architecture prevents accidental data exposure when using tools that automatically generate GraphQL schemas from Prisma models. The system relies on three primary middlewares that enforce constraints on fields, types, and lists based on @Auth annotations in the Prisma schema.
Sources: README.md:1-15, src/index.ts:40-44
Core Configuration Object
The Configuration interface defines how roles and global field behaviors are mapped to the authorization logic. You pass this object to makeAuthorizationMiddlewares to initialize the security layer.
| Property | Type | Description |
|---|---|---|
rolesPerType | RolesPerType | Map of model names to specific role definitions. |
globalRoles | Record<string, Role> | Role definitions applicable across all models. |
dmmf | any[] | Optional Prisma DMMF for model metadata. |
defaultFields | Record<string, object | function> | Fields always selected for a type. |
Sources: src/index.ts:16-32
Role Definition
Each role within the configuration contains logic for record-level matching and query-level filtering.
export interface Role<C, R, W> {
matcher: (context: C, record: R, roleArgs: RoleArgs) => boolean
queryConstraint: (context: C, roleArgs: RoleArgs) => W | boolean
matcherDependenciesSelect?: Record<string, any> | ((roleArgs: RoleArgs) => Record<string, any>)
}
Sources: src/index.ts:7-11
Authorization Middlewares
The system generates three distinct middlewares to handle different aspects of the GraphQL execution lifecycle.
1. Field Constraint Middleware
This middleware enforces authorization on individual fields. If a field in the Prisma model contains an /// @Auth comment, the middleware verifies that the current user satisfies at least one of the specified roles before returning the data. If access is denied, it returns a patched response (e.g., null or []).
Sources: src/makeFieldConstraintMiddleware.ts:14-53
2. Type Constraint Middleware
It enforces authorization on 1-to-1 relation fields. When a resolver returns a single object (non-list), this middleware checks the authorization requirements of that object's type.
Sources: src/makeTypeConstraintMiddleware.ts:25-63
3. List Constraint Middleware
This middleware handles list queries and nested relations. It performs two critical tasks:
- Selection Management: It uses
PrismaSelectto ensure only permitted fields are requested from the database. - Constraint Injection: It provides the
withAuthutility to the GraphQL context, which overlays mandatorywhereclauses onto Prisma queries.
Sources: src/makeListConstraintMiddleware.ts:26-77
Data Flow and Logic
The following diagram illustrates how a GraphQL request is processed through the authorization layers.
The system identifies @Auth annotations using a generated parser. It prioritizes rolesPerType over globalRoles when resolving a role name.
Sources: src/makeFieldConstraintMiddleware.ts:22-44, src/descriptionToRoles.ts:18-24
Query Constraint Generation
The getListWhereConstrains function translates role definitions into Prisma where filters.
- Role Mapping: It maps each authorized role to its
queryConstraint. - Result Handling:
- If
queryConstraintreturns an object, it is used directly. - If it returns
true, it uses analwaysTrueCondition. - If no constraints are met, it injects an
alwaysFalseCondition(filtering by a non-existent ID).
- If
- Logical Wrapping: Constraints are combined using
ORinside anANDblock to ensure they do not conflict with user-provided filters.
Sources: src/getListWhereConstrains.ts:31-68
Selection and Dependency Resolution
The library automatically extends Prisma select blocks to include fields required by role matchers.
The matcherDependenciesSelect property ensures that if a role matcher needs record.ownerId to verify ownership, that field is fetched even if the GraphQL client did not explicitly request it.
Sources: src/getMatcherDependenciesSelect.ts:11-33, src/select.ts:219-232
Summary
The @joindeed/prisma-auth middleware provides a robust security layer by integrating directly with Prisma's selection and filtering capabilities. By configuring globalRoles and rolesPerType, and utilizing the withAuth context helper, developers ensure that authorization logic is enforced consistently across all GraphQL resolvers and relation paths.
Sources: README.md:41-80, src/index.ts:40-44