Backend Middleware
The backend uses Nitro's middleware system to enforce security, logging, and operational logic globally. Middleware files are located in apps/backend-api/src/middleware/ and are executed in numeric/alphabetical order.
Middleware Execution Pipeline
The numbers in the filenames dictate the execution order. This hierarchy is critical for security:
- 0.5.correlation.ts: Tracing setup.
- 0.maintenance.ts: Global kill-switch.
- 1.logger.ts: Request logging.
- 2.auth.ts: Authentication & RBAC.
- 2.5.csrf.ts: CSRF Protection.
- 3.ratelimit.ts: Rate Limiting.
1. Correlation & Tracing (0.5.correlation.ts)
Purpose: Assigns a unique ID to every request to track it across logs and services.
- Logic:
- Checks for an existing ID in headers
X-Correlation-IDorX-Request-ID(useful for microservices). - If missing, generates a new
UUID. - Attaches the ID to the
event.context. - Sets the
X-Correlation-IDheader on the response.
- Checks for an existing ID in headers
2. Maintenance Mode (0.maintenance.ts)
Purpose: Allows administrators to lock the system for upgrades while keeping it accessible to themselves.
- Config Key:
maintenance_mode(inSystemConfigtable). - Logic:
- Exclusions: Skips
/api/healthand/api/statusso monitoring tools don't alert false positives. - Checks the global
maintenance_modesetting. - If Enabled:
- Verifies the user's authentication.
- Bypass: Allows the request if the user has the
superrole. - Block: Returns
503 Service Unavailablefor all other users.
- Exclusions: Skips
3. Operation Logging (1.logger.ts)
Purpose: Records a detailed audit trail of all API interactions.
- Data Source: Reads from
event.contextpopulated by other middleware (User, Correlation ID, Old/New Values). - Storage: Writes to the
OperationLogdatabase table. - Logic:
- Exclusions: Skips
/health,/test, and/uploads/to reduce noise. - Hooks into the response
finishevent to capture the final HTTP status code and duration. - Records: User, IP, Path, Method, Params, and Duration.
- Context: Can capture
operationDescription,oldValue, andnewValueif set by route handlers.
- Exclusions: Skips
4. Authentication & RBAC (2.auth.ts)
Purpose: The central security gatekeeper. Handles Identity (Who are you?) and Permissions (Can you do this?).
- Logic:
- Public Paths: Skips validation for Login, Refresh, MFA, and Health checks.
- Authentication (AuthN):
- Validates the JWT Access Token.
- Session Check: Verifies against the
UserSessiontable to ensure the session hasn't been revoked or expired. - Updates the session's
lastActiveAttimestamp.
- Authorization (AuthZ):
- Super Admin: Bypasses all permission checks.
- Route Matching: Matches the request path (
/api/users) to anApiPermissionrecord in the database. - Permission Check: Verifies if the user's Role is linked to that
ApiPermission. - Caching: Uses Valkey (Redis) to cache permission lookups for performance (
perms:role:...).
- Result:
401 Unauthorizedif invalid token/session.403 Forbiddenif role doesn't have permission.
5. CSRF Protection (2.5.csrf.ts)
Purpose: Prevents Cross-Site Request Forgery attacks using the Double-Submit Cookie pattern.
- Pattern: Requires both a cookie (
XSRF-TOKEN) and a matching header (X-XSRF-TOKEN). - Logic:
- Exclusions:
- Safe Methods:
GET,HEAD,OPTIONS. - Public Paths: Login, Refresh, MFA.
- Uploads:
/uploads/(handled via other means).
- Safe Methods:
- Reads the token from the Cookie and the Request Header.
- Validation:
- Both must exist.
- Both must match exactly.
- Result:
403 Forbiddenon mismatch.
- Exclusions:
6. Rate Limiting (3.ratelimit.ts)
Purpose: Protects the API from abuse, brute-force attacks, and DoS attempts.
- Storage: Uses the
RateLimittable (PostgreSQL). - Rules:
- Auth Endpoints: 100 requests / 15 mins (Strict).
- User Creation: 50 requests / 1 hour (Anti-spam).
- Password Reset: 5 requests / 1 hour (High security).
- File Uploads: 100 requests / 1 hour.
- General API: 60 requests / 1 minute.
- Logic:
- Identifies the rule based on the request path.
- Atomic Counting: Performs a database Upsert (Insert or Update) to increment the counter for the IP address.
- Enforcement:
- If count > limit, returns
429 Too Many Requests. - Returns a
Retry-Aftermessage.
- If count > limit, returns