Middleware Pipeline
Relevant source files
The following files were used as context for generating this wiki page:
The Middleware Pipeline in MuteTaxes serves as the primary enforcement mechanism for authentication and Relationship-Based Access Control (ReBAC). It ensures that every incoming request to a protected resource is validated against the user's identity and their specific permissions stored within OpenFGA. By decoupling authorization logic from business logic, the pipeline provides a standardized way to protect API endpoints based on granular CRUD actions.
The pipeline is structured as a series of Express.js middleware functions that handle authentication, administrative privilege verification, and resource-specific authorization. This modular approach allows the system to support a demo environment where roles and permissions can be dynamically adjusted and instantly reflected in the API's behavior.
Sources: PLAN.md:14-22, backend/src/index.ts:14-25
Core Middleware Components
The pipeline consists of three primary specialized middleware functions, typically executed in a specific sequence to ensure multiple layers of security.
| Middleware | Purpose | Key Dependency |
|---|---|---|
authenticate | Validates JWT and attaches user context to the request. | jsonwebtoken |
requireSuperAdmin | Restricts access to global administrative actions (User/Role/Table management). | prisma |
authorizeTable | Performs ReBAC checks for specific CRUD operations on resource tables. | OpenFGA |
Sources: backend/src/middleware/auth.ts, backend/src/middleware/requireSuperAdmin.ts, backend/src/middleware/authorizeTable.ts, PLAN.md:89-95
Authentication Layer
The authenticate middleware is the entry point for all protected routes. It extracts the Bearer token from the Authorization header, verifies the JWT, and retrieves the corresponding user record from the database. If successful, it populates req.user for downstream middleware.
Sources: backend/src/middleware/auth.ts:1-20, PLAN.md:146-150
ReBAC Authorization Layer
The authorizeTable middleware integrates directly with the OpenFGA client. It takes an action (e.g., "read", "create") and a table slug as parameters. It calls checkPermission using the current user's ID to determine if the relationship exists in the authorization model.
The diagram above illustrates the request flow through the security layers before reaching the final request handler.
Sources: backend/src/middleware/authorizeTable.ts:5-15, backend/src/modules/demo/demo.routes.ts:1-20
Implementation Patterns
Route Protection Examples
Routes are protected by chaining middleware. Administrative routes require both authentication and super-admin status, while resource routes use the table authorizer.
| Route Type | Example Middleware Chain | File Reference |
|---|---|---|
| Global Admin | authenticate, requireSuperAdmin | backend/src/modules/users/users.routes.ts |
| Resource Access | authenticate, authorizeTable('read', 'clients') | backend/src/modules/demo/demo.routes.ts |
Demo Resource Protection
In the demo module, CRUD operations on the clients table are individually protected by specifying the required FGA action.
// backend/src/modules/demo/demo.routes.ts:9-20
demoRoutes.get("/clients", authorizeTable("read", "clients"), (_req, res) => {
return res.json({ data: [{ id: "c1", name: "Acme Corp" }] });
});
demoRoutes.post("/clients", authorizeTable("create", "clients"), (_req, res) => {
return res.status(201).json({ ok: true });
});
Sources: backend/src/modules/demo/demo.routes.ts:9-20, backend/src/modules/users/users.routes.ts:9-11
Data Flow for Authorization
When authorizeTable is invoked, it triggers a sequence diagram flow involving the OpenFGA server to validate the user's relationship to the object.
Error Handling Pipeline
The pipeline includes a global error handling middleware located in the main application entry point. This ensures that any failures in the middleware chain or controllers do not leak sensitive implementation details and return a standardized JSON error response.
- Status 401: Returned by
authenticatewhen the JWT is missing or invalid. - Status 403: Returned by
requireSuperAdminorauthorizeTablewhen permissions are insufficient. - Status 500: Returned by the final error handler for unhandled exceptions.
Sources: backend/src/index.ts:21-24, backend/src/middleware/auth.ts:18, backend/src/middleware/authorizeTable.ts:17
Summary
The Middleware Pipeline is the backbone of the MuteTaxes authorization strategy. By utilizing a layered approach—starting with JWT authentication and ending with OpenFGA-backed ReBAC—the system provides a secure and flexible environment for managing resource access. This architecture allows the application to scale permissions from simple role memberships to complex relationship-based rules without modifying route handlers.