security: Add authMiddleware to analytics-v2 routes
- Add authMiddleware to analytics-v2.ts to require authentication - Add permanent rule #6 to CLAUDE.md: "ALL API ROUTES REQUIRE AUTHENTICATION" - Add forbidden action #19: "Creating API routes without authMiddleware" - Document authentication flow and trusted origins 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
38
CLAUDE.md
38
CLAUDE.md
@@ -119,7 +119,42 @@ npx tsx src/db/migrate.ts
|
|||||||
- Importing it at runtime causes startup crashes if env vars aren't perfect
|
- Importing it at runtime causes startup crashes if env vars aren't perfect
|
||||||
- `pool.ts` uses lazy initialization - only validates when first query is made
|
- `pool.ts` uses lazy initialization - only validates when first query is made
|
||||||
|
|
||||||
### 6. LOCAL DEVELOPMENT BY DEFAULT
|
### 6. ALL API ROUTES REQUIRE AUTHENTICATION — NO EXCEPTIONS
|
||||||
|
|
||||||
|
**Every API router MUST apply `authMiddleware` at the router level.**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { authMiddleware } from '../auth/middleware';
|
||||||
|
|
||||||
|
const router = Router();
|
||||||
|
router.use(authMiddleware); // REQUIRED - first line after router creation
|
||||||
|
```
|
||||||
|
|
||||||
|
**Authentication flow (see `src/auth/middleware.ts`):**
|
||||||
|
1. Check Bearer token (JWT or API token) → grant access if valid
|
||||||
|
2. Check trusted origins (cannaiq.co, findadispo.com, localhost, etc.) → grant access
|
||||||
|
3. Check trusted IPs (127.0.0.1, ::1, internal pod IPs) → grant access
|
||||||
|
4. **Return 401 Unauthorized** if none of the above
|
||||||
|
|
||||||
|
**NEVER create API routes without auth middleware:**
|
||||||
|
- No "public" endpoints that bypass authentication
|
||||||
|
- No "read-only" exceptions
|
||||||
|
- No "analytics-only" exceptions
|
||||||
|
- If an endpoint exists under `/api/*`, it MUST be protected
|
||||||
|
|
||||||
|
**When creating new route files:**
|
||||||
|
1. Import `authMiddleware` from `../auth/middleware`
|
||||||
|
2. Add `router.use(authMiddleware)` immediately after creating the router
|
||||||
|
3. Document security requirements in file header comments
|
||||||
|
|
||||||
|
**Trusted origins (defined in middleware):**
|
||||||
|
- `https://cannaiq.co`
|
||||||
|
- `https://findadispo.com`
|
||||||
|
- `https://findagram.co`
|
||||||
|
- `*.cannabrands.app` domains
|
||||||
|
- `localhost:*` for development
|
||||||
|
|
||||||
|
### 7. LOCAL DEVELOPMENT BY DEFAULT
|
||||||
|
|
||||||
**Quick Start:**
|
**Quick Start:**
|
||||||
```bash
|
```bash
|
||||||
@@ -452,6 +487,7 @@ const result = await pool.query(`
|
|||||||
16. **Running `lsof -ti:PORT | xargs kill`** or similar process-killing commands
|
16. **Running `lsof -ti:PORT | xargs kill`** or similar process-killing commands
|
||||||
17. **Using hardcoded database names** in code or comments
|
17. **Using hardcoded database names** in code or comments
|
||||||
18. **Creating or connecting to a second database**
|
18. **Creating or connecting to a second database**
|
||||||
|
19. **Creating API routes without authMiddleware** (all `/api/*` routes MUST be protected)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,17 @@
|
|||||||
* Routes are prefixed with /api/analytics/v2
|
* Routes are prefixed with /api/analytics/v2
|
||||||
*
|
*
|
||||||
* Phase 3: Analytics Engine + Rec/Med by State
|
* Phase 3: Analytics Engine + Rec/Med by State
|
||||||
|
*
|
||||||
|
* SECURITY: All routes require authentication via authMiddleware.
|
||||||
|
* Access is granted to:
|
||||||
|
* - Trusted origins (cannaiq.co, findadispo.com, etc.)
|
||||||
|
* - Trusted IPs (localhost, internal pods)
|
||||||
|
* - Valid JWT or API tokens
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Router, Request, Response } from 'express';
|
import { Router, Request, Response } from 'express';
|
||||||
import { Pool } from 'pg';
|
import { Pool } from 'pg';
|
||||||
|
import { authMiddleware } from '../auth/middleware';
|
||||||
import { PriceAnalyticsService } from '../services/analytics/PriceAnalyticsService';
|
import { PriceAnalyticsService } from '../services/analytics/PriceAnalyticsService';
|
||||||
import { BrandPenetrationService } from '../services/analytics/BrandPenetrationService';
|
import { BrandPenetrationService } from '../services/analytics/BrandPenetrationService';
|
||||||
import { CategoryAnalyticsService } from '../services/analytics/CategoryAnalyticsService';
|
import { CategoryAnalyticsService } from '../services/analytics/CategoryAnalyticsService';
|
||||||
@@ -36,6 +43,10 @@ function parseLegalType(legalType?: string): LegalType {
|
|||||||
export function createAnalyticsV2Router(pool: Pool): Router {
|
export function createAnalyticsV2Router(pool: Pool): Router {
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
|
// SECURITY: Apply auth middleware to ALL routes
|
||||||
|
// This gate ensures only authenticated requests can access analytics data
|
||||||
|
router.use(authMiddleware);
|
||||||
|
|
||||||
// Initialize services
|
// Initialize services
|
||||||
const priceService = new PriceAnalyticsService(pool);
|
const priceService = new PriceAnalyticsService(pool);
|
||||||
const brandService = new BrandPenetrationService(pool);
|
const brandService = new BrandPenetrationService(pool);
|
||||||
|
|||||||
Reference in New Issue
Block a user