Skip to content

API Security Model

The middleware has been updated to implement a more secure and specific authentication model for API routes. Instead of blanket-skipping authentication for all API routes, we now categorize them and require appropriate guards. Unknown API routes now enforce authentication by default for security.

1. Public API Routes (No Authentication Required)

Section titled “1. Public API Routes (No Authentication Required)”
  • /api/health - Health checks for monitoring
  • /api/contact - Contact form submissions

2. Admin API Routes (Require Admin Authentication)

Section titled “2. Admin API Routes (Require Admin Authentication)”
  • /api/admin/* - All admin operations
  • /api/cache/* - Cache management operations
  • /api/maintenance/* - System maintenance operations
  • /api/debug/* - Debugging endpoints
  • /api/tests/* - Testing endpoints

3. Protected API Routes (Require Regular Authentication)

Section titled “3. Protected API Routes (Require Regular Authentication)”
  • /api/auth/* - Authentication operations
  • /api/erp/* - ERP-related operations
  • /api/orders/* - Order management
  • /api/extracted-orders/* - Extracted order operations
  • /api/pdf-documents/* - PDF document operations
  • /api/support/* - Support operations
  • /api/trigger/webhooks - Webhook endpoints

4. Unknown API Routes (Default to Authentication Required) ⚠️ SECURITY ENFORCED

Section titled “4. Unknown API Routes (Default to Authentication Required) ⚠️ SECURITY ENFORCED”
  • Any new API routes not explicitly categorized WILL REQUIRE AUTHENTICATION
  • Returns HTTP 401 Unauthorized if no valid user session is found
  • Prevents unauthorized access to potentially sensitive endpoints
  • Security by default - no accidental exposure of new endpoints

All admin API endpoints MUST call requireAdmin(locals, request) at the start of their handler:

class AdminHandler extends BaseAPIHandler {
async GET({ locals, request }: any): Promise<Response> {
return this.handleRequest(async () => {
// REQUIRED: Check authentication and admin permissions
const { userId } = await this.requireAdmin(locals, request);
// Your handler logic here...
// userId is guaranteed to be valid and belong to an admin
});
}
}

All protected API endpoints MUST call requireAuth(locals, request) at the start of their handler:

class ProtectedHandler extends BaseAPIHandler {
async POST({ locals, request }: any): Promise<Response> {
return this.handleRequest(async () => {
// REQUIRED: Check authentication
const { userId } = await this.requireAuth(locals, request);
// Your handler logic here...
// userId is guaranteed to be valid
});
}
}

Public API endpoints don’t need authentication guards, but should still use proper input validation and rate limiting.

🚨 NEW: Default Authentication Enforcement

Section titled “🚨 NEW: Default Authentication Enforcement”

When a request is made to an uncategorized API route:

  1. Middleware attempts authentication using getUserFromSession(request)
  2. If authentication succeeds: User is attached to context.locals.user and request proceeds
  3. If authentication fails or no user: HTTP 401 Unauthorized is returned immediately
  4. Request never reaches the handler - security is enforced at the middleware level
{
"error": "Unauthorized",
"message": "Authentication required for this endpoint",
"code": "AUTHENTICATION_REQUIRED"
}
  • No accidental exposure of new endpoints
  • Consistent authentication across all unknown routes
  • Immediate rejection of unauthorized requests
  • Clear error messages for debugging
  • /api/admin/system-stats.ts - Uses requireAdmin
  • /api/admin/rate-limiting.ts - Uses requireAdmin
  • /api/admin/unblock-ip.ts - Uses requireAdmin
  • /api/cache/flush.ts - Uses requireAdmin
  • /api/cache/stats.ts - Uses requireAdmin
  • /api/maintenance/* - Verify admin guards
  • /api/debug/* - Verify admin guards
  • /api/tests/* - Verify admin guards
  • /api/auth/* - Verify auth guards
  • /api/erp/* - Verify auth guards
  • /api/orders/* - Verify auth guards
  • /api/extracted-orders/* - Verify auth guards
  • /api/pdf-documents/* - Verify auth guards
  • /api/support/* - Verify auth guards
  • All API routes skipped authentication in middleware
  • Individual handlers had to remember to implement guards
  • Risk of forgetting to add requireAuth or requireAdmin
  • Potential for unauthorized access to sensitive operations
  • Unknown routes could proceed unauthenticated
  • Middleware categorizes routes and requires authentication where appropriate
  • Individual handlers still need guards, but middleware provides a safety net
  • Unknown routes default to requiring authentication
  • Immediate 401 rejection for unauthorized requests to unknown routes
  • Clear separation between public, protected, and admin endpoints
  • Security by default - no accidental exposure
  • Verify all /api/admin/* endpoints use requireAdmin(locals, request)
  • Verify all /api/cache/* endpoints use requireAdmin(locals, request)
  • Verify all /api/maintenance/* endpoints use requireAdmin(locals, request)
  • Verify all /api/debug/* endpoints use requireAdmin(locals, request)
  • Verify all /api/tests/* endpoints use requireAdmin(locals, request)
  • Verify all /api/auth/* endpoints use requireAuth(locals, request)
  • Verify all /api/erp/* endpoints use requireAuth(locals, request)
  • Verify all /api/orders/* endpoints use requireAuth(locals, request)
  • Verify all /api/extracted-orders/* endpoints use requireAuth(locals, request)
  • Verify all /api/pdf-documents/* endpoints use requireAuth(locals, request)
  • Verify all /api/support/* endpoints use requireAuth(locals, request)
  • Test that public routes (/api/health, /api/contact) work without authentication
  • Test that protected routes reject unauthenticated requests
  • Test that admin routes reject non-admin users
  • Test that unknown API routes return 401 Unauthorized ⚠️ NEW

When adding new API routes:

  1. Determine the security category (public, protected, or admin)
  2. Add the route to the appropriate array in middleware.ts
  3. Implement the appropriate guard in your handler
  4. Test authentication requirements work as expected
// In middleware.ts, add to adminApiRoutes:
const adminApiRoutes = [
'/api/admin',
'/api/cache',
'/api/maintenance',
'/api/debug',
'/api/tests',
'/api/admin/new-feature', // Add your new route here
];
// In your handler:
class NewFeatureHandler extends BaseAPIHandler {
async POST({ locals, request }: any): Promise<Response> {
return this.handleRequest(async () => {
const { userId } = await this.requireAdmin(locals, request);
// Your handler logic here...
});
}
}

If you forget to add a new route to the appropriate category array, the middleware will automatically enforce authentication and return 401 for unauthorized requests. This provides a security safety net but means you should always categorize your routes properly.

  1. Improved Security - No more accidentally forgetting authentication
  2. Clear Categorization - Easy to understand which routes need what level of auth
  3. Defense in Depth - Middleware + handler guards provide multiple security layers
  4. Maintainable - Clear patterns for implementing new secure endpoints
  5. Production Ready - Prevents the authentication failures that were causing app crashes
  6. Security by Default - Unknown routes automatically require authentication
  7. Immediate Rejection - Unauthorized requests to unknown routes get 401 immediately