CognxSafeTrack commited on
Commit
9595ade
Β·
1 Parent(s): 7cf001f

fix(auth): inline onRequest hook in guardedRoutes scope to properly protect private routes

Browse files
Files changed (1) hide show
  1. apps/api/src/index.ts +25 -7
apps/api/src/index.ts CHANGED
@@ -1,7 +1,6 @@
1
  import Fastify from 'fastify';
2
  import cors from '@fastify/cors';
3
  import rateLimit from '@fastify/rate-limit';
4
- import authPlugin from './plugins/auth';
5
  import { whatsappRoutes } from './routes/whatsapp';
6
  import { adminRoutes } from './routes/admin';
7
  import { aiRoutes } from './routes/ai';
@@ -26,12 +25,31 @@ server.register(rateLimit, {
26
  server.register(whatsappRoutes, { prefix: '/v1/whatsapp' });
27
 
28
  // ── Private Routes (require ADMIN_API_KEY) ─────────────────────────────────────
29
- // Each private scope gets its own auth guard β€” they cannot be bypassed
30
- server.register(async (privateScope) => {
31
- privateScope.register(authPlugin);
32
- privateScope.register(adminRoutes, { prefix: '/v1/admin' });
33
- privateScope.register(aiRoutes, { prefix: '/v1/ai' });
34
- privateScope.register(paymentRoutes, { prefix: '/v1/payments' });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  });
36
 
37
  // ── Health Routes (public) ─────────────────────────────────────────────────────
 
1
  import Fastify from 'fastify';
2
  import cors from '@fastify/cors';
3
  import rateLimit from '@fastify/rate-limit';
 
4
  import { whatsappRoutes } from './routes/whatsapp';
5
  import { adminRoutes } from './routes/admin';
6
  import { aiRoutes } from './routes/ai';
 
25
  server.register(whatsappRoutes, { prefix: '/v1/whatsapp' });
26
 
27
  // ── Private Routes (require ADMIN_API_KEY) ─────────────────────────────────────
28
+ // Inline addHook on an isolated scope guarantees the auth check fires BEFORE
29
+ // any child route handler, properly encapsulated in Fastify v4.
30
+ server.register(async function guardedRoutes(scope) {
31
+ scope.addHook('onRequest', async (request, reply) => {
32
+ const apiKey = process.env.ADMIN_API_KEY;
33
+
34
+ if (!apiKey) {
35
+ request.log.error('ADMIN_API_KEY is not configured!');
36
+ return reply.code(503).send({ error: 'Service misconfigured' });
37
+ }
38
+
39
+ const authHeader = request.headers['authorization'];
40
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
41
+ return reply.code(401).send({ error: 'Unauthorized', message: 'Missing Authorization header' });
42
+ }
43
+
44
+ const token = authHeader.slice(7);
45
+ if (token !== apiKey) {
46
+ return reply.code(401).send({ error: 'Unauthorized', message: 'Invalid API key' });
47
+ }
48
+ });
49
+
50
+ scope.register(adminRoutes, { prefix: '/v1/admin' });
51
+ scope.register(aiRoutes, { prefix: '/v1/ai' });
52
+ scope.register(paymentRoutes, { prefix: '/v1/payments' });
53
  });
54
 
55
  // ── Health Routes (public) ─────────────────────────────────────────────────────