@wazobiatech/auth-middleware 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,9 +1,3 @@
1
1
  export * from './middlewares';
2
- export * from './nestjs/jwt-auth.module';
3
- export * from './nestjs/strategies/jwt-strategy';
4
- export * from './nestjs/guards/jwt-guard';
5
- export * from './nestjs/guards/project.guard';
6
- export * from './nestjs/decorators/auth.decorator';
7
- export * from './nestjs/decorators/current-user.decorator';
8
2
  export * from './types/jwt-payload';
9
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC;AACzC,cAAc,kCAAkC,CAAC;AACjD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,oCAAoC,CAAC;AACnD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -15,11 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./middlewares"), exports);
18
- __exportStar(require("./nestjs/jwt-auth.module"), exports);
19
- __exportStar(require("./nestjs/strategies/jwt-strategy"), exports);
20
- __exportStar(require("./nestjs/guards/jwt-guard"), exports);
21
- __exportStar(require("./nestjs/guards/project.guard"), exports);
22
- __exportStar(require("./nestjs/decorators/auth.decorator"), exports);
23
- __exportStar(require("./nestjs/decorators/current-user.decorator"), exports);
24
18
  __exportStar(require("./types/jwt-payload"), exports);
25
19
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,2DAAyC;AACzC,mEAAiD;AACjD,4DAA0C;AAC1C,gEAA6C;AAC7C,qEAAmD;AACnD,6EAA2D;AAC3D,sDAAmC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,sDAAoC"}
@@ -2,4 +2,5 @@ export { ProjectAuthMiddleware } from "./project.guard";
2
2
  export { JwtAuthMiddleware } from "./jwt.guard";
3
3
  export { GraphQLAuthHelper } from "./gql.helper";
4
4
  export { projectAuthMiddleware, jwtAuthMiddleware } from "./express.helper";
5
+ export * from '../types/jwt-payload';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middlewares/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middlewares/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAC3E,cAAc,sBAAsB,CAAC"}
@@ -1,4 +1,18 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
17
  exports.jwtAuthMiddleware = exports.projectAuthMiddleware = exports.GraphQLAuthHelper = exports.JwtAuthMiddleware = exports.ProjectAuthMiddleware = void 0;
4
18
  var project_guard_1 = require("./project.guard");
@@ -10,4 +24,5 @@ Object.defineProperty(exports, "GraphQLAuthHelper", { enumerable: true, get: fun
10
24
  var express_helper_1 = require("./express.helper");
11
25
  Object.defineProperty(exports, "projectAuthMiddleware", { enumerable: true, get: function () { return express_helper_1.projectAuthMiddleware; } });
12
26
  Object.defineProperty(exports, "jwtAuthMiddleware", { enumerable: true, get: function () { return express_helper_1.jwtAuthMiddleware; } });
27
+ __exportStar(require("../types/jwt-payload"), exports);
13
28
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middlewares/index.ts"],"names":[],"mappings":";;;AAAA,iDAAuD;AAA9C,sHAAA,qBAAqB,OAAA;AAC9B,yCAA+C;AAAtC,8GAAA,iBAAiB,OAAA;AAC1B,2CAAgD;AAAvC,+GAAA,iBAAiB,OAAA;AAC1B,mDAA2E;AAAlE,uHAAA,qBAAqB,OAAA;AAAE,mHAAA,iBAAiB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middlewares/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,iDAAuD;AAA9C,sHAAA,qBAAqB,OAAA;AAC9B,yCAA+C;AAAtC,8GAAA,iBAAiB,OAAA;AAC1B,2CAAgD;AAAvC,+GAAA,iBAAiB,OAAA;AAC1B,mDAA2E;AAAlE,uHAAA,qBAAqB,OAAA;AAAE,mHAAA,iBAAiB,OAAA;AACjD,uDAAqC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wazobiatech/auth-middleware",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Framework-agnostic JWT authentication library for Wazobia microservices platform",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -22,11 +22,11 @@
22
22
  "author": "Platform Team",
23
23
  "license": "MIT",
24
24
  "peerDependencies": {
25
- "@nestjs/common": "^10.0.0",
26
- "@nestjs/passport": "^10.0.0",
27
- "@nestjs/graphql": "^12.0.8",
28
- "express": "^4.18.0",
29
- "fastify": "^4.0.0",
25
+ "@nestjs/common": "^10.0.0 || ^11.0.0",
26
+ "@nestjs/graphql": "^12.0.0",
27
+ "@nestjs/passport": "^10.0.0 || ^11.0.0",
28
+ "express": "^4.18.0 || ^5.0.0",
29
+ "fastify": "^4.0.0 || ^5.0.0",
30
30
  "ioredis": "^5.0.0",
31
31
  "passport-jwt": "^4.0.0"
32
32
  },
@@ -58,6 +58,10 @@
58
58
  "types": "./dist/index.d.ts",
59
59
  "default": "./dist/index.js"
60
60
  },
61
+ "./express": {
62
+ "types": "./dist/express/index.d.ts",
63
+ "default": "./dist/express/index.js"
64
+ },
61
65
  "./nestjs": {
62
66
  "types": "./dist/nestjs/index.d.ts",
63
67
  "default": "./dist/nestjs/index.js"
@@ -65,36 +69,42 @@
65
69
  },
66
70
  "typesVersions": {
67
71
  "*": {
72
+ "express": [
73
+ "dist/express/index.d.ts"
74
+ ],
68
75
  "nestjs": [
69
76
  "dist/nestjs/index.d.ts"
70
77
  ]
71
78
  }
72
79
  },
73
80
  "dependencies": {
74
- "@nestjs/common": "^11.1.5",
75
- "@nestjs/passport": "^11.0.5",
76
81
  "axios": "^1.6.0",
77
- "express": "^5.1.0",
78
- "fastify": "^5.4.0",
79
- "fastify-plugin": "^5.0.1",
80
- "redis": "^5.1.1",
82
+ "dotenv": "^16.3.1",
81
83
  "jsonwebtoken": "^9.0.0",
82
84
  "node-jose": "^2.2.0",
83
- "passport-jwt": "^4.0.1",
84
- "passport": "^0.7.0",
85
- "graphql": "^16.11.0",
86
- "dotenv": "^16.3.1"
85
+ "passport": "^0.7.0"
87
86
  },
88
87
  "devDependencies": {
88
+ "@nestjs/common": "^11.1.5",
89
+ "@nestjs/core": "^11.1.5",
90
+ "@nestjs/schematics": "^11.0.7",
91
+ "@nestjs/graphql": "^12.0.8",
92
+ "@nestjs/passport": "^11.0.5",
93
+ "@nestjs/testing": "^11.1.5",
89
94
  "@types/express": "^5.0.3",
90
95
  "@types/jest": "^29.0.0",
91
96
  "@types/jsonwebtoken": "^9.0.0",
92
97
  "@types/node": "^20.0.0",
93
98
  "@types/node-jose": "^1.1.13",
94
99
  "@types/passport-jwt": "^4.0.1",
95
- "@nestjs/testing": "^11.1.5",
96
- "@nestjs/graphql": "^12.0.8",
100
+ "express": "^5.1.0",
101
+ "fastify": "^5.4.0",
102
+ "graphql": "^16.11.0",
97
103
  "jest": "^29.0.0",
104
+ "passport-jwt": "^4.0.1",
105
+ "redis": "^5.1.1",
106
+ "reflect-metadata": "^0.2.2",
107
+ "rxjs": "^7.8.0",
98
108
  "ts-jest": "^29.0.0",
99
109
  "typescript": "^5.0.0"
100
110
  }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=middleware.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"middleware.test.d.ts","sourceRoot":"","sources":["../../src/test/middleware.test.ts"],"names":[],"mappings":""}
@@ -1,383 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const middlewares_1 = require("../middlewares");
4
- const jwt = require("jsonwebtoken");
5
- const axios_1 = require("axios");
6
- const redis_1 = require("redis");
7
- // Mock dependencies
8
- jest.mock('redis');
9
- jest.mock('axios');
10
- jest.mock('jsonwebtoken');
11
- jest.mock('node-jose');
12
- const mockRedis = {
13
- sendCommand: jest.fn(),
14
- connect: jest.fn(),
15
- on: jest.fn(),
16
- quit: jest.fn()
17
- };
18
- const mockAxios = axios_1.default;
19
- const mockJwt = jwt;
20
- const mockCreateClient = redis_1.createClient;
21
- describe('ProjectAuthMiddleware', () => {
22
- let middleware;
23
- let mockReq;
24
- let mockRes;
25
- let mockNext;
26
- beforeEach(() => {
27
- // Reset mocks
28
- jest.clearAllMocks();
29
- // Setup Redis mock
30
- mockCreateClient.mockReturnValue(mockRedis);
31
- // Setup Express mocks with proper typing
32
- mockReq = {
33
- headers: {},
34
- project: undefined,
35
- // Add minimal Express Request properties that might be used
36
- get: jest.fn(),
37
- header: jest.fn(),
38
- params: {},
39
- query: {},
40
- body: {},
41
- url: '/',
42
- method: 'GET'
43
- };
44
- mockRes = {
45
- status: jest.fn().mockReturnThis(),
46
- json: jest.fn().mockReturnThis(),
47
- send: jest.fn().mockReturnThis(),
48
- end: jest.fn().mockReturnThis()
49
- };
50
- mockNext = jest.fn();
51
- // Environment variables
52
- process.env.REDIS_URL = 'redis://localhost:6379';
53
- process.env.MERCURY_BASE_URL = 'http://localhost:4000';
54
- process.env.SERVICE_ID = 'test-service';
55
- middleware = new middlewares_1.ProjectAuthMiddleware();
56
- });
57
- describe('Unit Tests - authenticate()', () => {
58
- it('should reject requests without x-project-token header', async () => {
59
- await middleware.authenticate(mockReq);
60
- expect(mockRes.status).toHaveBeenCalledWith(401);
61
- expect(mockRes.json).toHaveBeenCalledWith({
62
- error: 'No project token provided',
63
- required_header: 'x-project-token'
64
- });
65
- expect(mockNext).not.toHaveBeenCalled();
66
- });
67
- it('should reject requests with empty token', async () => {
68
- mockReq.headers['x-project-token'] = '';
69
- await middleware.authenticate(mockReq);
70
- expect(mockRes.status).toHaveBeenCalledWith(401);
71
- expect(mockRes.json).toHaveBeenCalledWith({
72
- error: 'Empty project token'
73
- });
74
- });
75
- it('should extract token from Bearer format', async () => {
76
- const testToken = 'valid.jwt.token';
77
- mockReq.headers['x-project-token'] = `Bearer ${testToken}`;
78
- // Mock successful validation
79
- const mockPayload = {
80
- project_uuid: 'test-project',
81
- enabled_services: ['test-service'],
82
- secret_version: 1,
83
- token_id: 'token-123',
84
- exp: Math.floor(Date.now() / 1000) + 3600
85
- };
86
- const mockValidation = jest.spyOn(middleware, 'validateProjectToken');
87
- mockValidation.mockResolvedValue({
88
- isValid: true,
89
- payload: mockPayload
90
- });
91
- await middleware.authenticate(mockReq);
92
- expect(mockValidation).toHaveBeenCalledWith(testToken);
93
- expect(mockNext).toHaveBeenCalled();
94
- });
95
- it('should reject when SERVICE_ID not configured', async () => {
96
- delete process.env.SERVICE_ID;
97
- mockReq.headers['x-project-token'] = 'Bearer valid.token';
98
- await middleware.authenticate(mockReq);
99
- expect(mockRes.status).toHaveBeenCalledWith(500);
100
- expect(mockRes.json).toHaveBeenCalledWith({
101
- error: 'Service ID not configured'
102
- });
103
- });
104
- it('should reject when service not in enabled_services', async () => {
105
- mockReq.headers['x-project-token'] = 'Bearer valid.token';
106
- const mockPayload = {
107
- project_uuid: 'test-project',
108
- enabled_services: ['other-service'], // test-service not included
109
- secret_version: 1,
110
- token_id: 'token-123',
111
- exp: Math.floor(Date.now() / 1000) + 3600
112
- };
113
- const mockValidation = jest.spyOn(middleware, 'validateProjectToken');
114
- mockValidation.mockResolvedValue({
115
- isValid: true,
116
- payload: mockPayload
117
- });
118
- await middleware.authenticate(mockReq);
119
- expect(mockRes.status).toHaveBeenCalledWith(403);
120
- expect(mockRes.json).toHaveBeenCalledWith({
121
- error: 'Service access denied',
122
- service_id: 'test-service',
123
- project: 'test-project',
124
- enabled_services: ['other-service']
125
- });
126
- });
127
- it('should inject project context on successful validation', async () => {
128
- mockReq.headers['x-project-token'] = 'Bearer valid.token';
129
- const mockPayload = {
130
- project_uuid: 'test-project',
131
- enabled_services: ['test-service'],
132
- secret_version: 1,
133
- token_id: 'token-123',
134
- exp: Math.floor(Date.now() / 1000) + 3600
135
- };
136
- const mockValidation = jest.spyOn(middleware, 'validateProjectToken');
137
- mockValidation.mockResolvedValue({
138
- isValid: true,
139
- payload: mockPayload
140
- });
141
- await middleware.authenticate(mockReq);
142
- expect(mockReq.project).toEqual({
143
- project_uuid: 'test-project',
144
- enabled_services: ['test-service'],
145
- secret_version: 1,
146
- token_id: 'token-123',
147
- expires_at: mockPayload.exp
148
- });
149
- expect(mockNext).toHaveBeenCalled();
150
- });
151
- });
152
- describe('Unit Tests - validateProjectToken()', () => {
153
- it('should validate JWT structure and check Redis cache', async () => {
154
- const testToken = 'valid.jwt.token';
155
- const mockPayload = {
156
- project_uuid: 'test-project',
157
- token_id: 'token-123',
158
- enabled_services: ['test-service']
159
- };
160
- // Mock JWT verification
161
- mockJwt.verify.mockReturnValue(mockPayload);
162
- // Mock Redis EXISTS check
163
- mockRedis.sendCommand.mockResolvedValue(1); // Token exists
164
- // Mock getPublicKeyFromCache
165
- const mockGetPublicKey = jest.spyOn(middleware, 'getPublicKeyFromCache');
166
- mockGetPublicKey.mockResolvedValue('mock-public-key');
167
- const result = await middleware.validateProjectToken(testToken);
168
- expect(result.isValid).toBe(true);
169
- expect(result.payload).toEqual(mockPayload);
170
- expect(mockJwt.verify).toHaveBeenCalledWith(testToken, 'mock-public-key', { algorithms: ['RS256', 'RS512'], ignoreExpiration: false });
171
- });
172
- it('should return invalid when token revoked', async () => {
173
- const testToken = 'revoked.jwt.token';
174
- const mockPayload = {
175
- project_uuid: 'test-project',
176
- token_id: 'token-123',
177
- enabled_services: ['test-service']
178
- };
179
- mockJwt.verify.mockReturnValue(mockPayload);
180
- mockRedis.sendCommand.mockResolvedValue(0); // Token doesn't exist (revoked)
181
- const mockGetPublicKey = jest.spyOn(middleware, 'getPublicKeyFromCache');
182
- mockGetPublicKey.mockResolvedValue('mock-public-key');
183
- const result = await middleware.validateProjectToken(testToken);
184
- expect(result.isValid).toBe(false);
185
- expect(result.error).toBe('Token has been revoked');
186
- });
187
- });
188
- describe('Unit Tests - JWKS Caching', () => {
189
- it('should fetch and cache JWKS on cache miss', async () => {
190
- const mockJwksResponse = {
191
- data: {
192
- keys: [
193
- { kid: 'key-1', kty: 'RSA', use: 'sig' }
194
- ]
195
- }
196
- };
197
- // Mock Redis cache miss
198
- mockRedis.sendCommand.mockResolvedValueOnce(null); // GET returns null
199
- // Mock axios response
200
- mockAxios.get.mockResolvedValue(mockJwksResponse);
201
- // Mock jose keystore
202
- const mockKeyStore = {
203
- get: jest.fn().mockReturnValue({
204
- toPEM: jest.fn().mockReturnValue('mock-pem-key')
205
- })
206
- };
207
- const jose = require('node-jose');
208
- jose.JWK.asKeyStore = jest.fn().mockResolvedValue(mockKeyStore);
209
- const testToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImtleS0xIn0.payload.signature';
210
- const result = await middleware.getPublicKeyFromCache(testToken);
211
- expect(mockAxios.get).toHaveBeenCalledWith('http://localhost:4000/auth/projects/auth/project/.well-known/jwks.json', expect.any(Object));
212
- expect(mockRedis.sendCommand).toHaveBeenCalledWith([
213
- 'SETEX',
214
- 'project_jwks_cache',
215
- '18000',
216
- JSON.stringify(mockJwksResponse.data)
217
- ]);
218
- expect(result).toBe('mock-pem-key');
219
- });
220
- it('should use cached JWKS on cache hit', async () => {
221
- const mockCachedJwks = JSON.stringify({
222
- keys: [{ kid: 'key-1', kty: 'RSA', use: 'sig' }]
223
- });
224
- // Mock Redis cache hit
225
- mockRedis.sendCommand.mockResolvedValueOnce(mockCachedJwks);
226
- const mockKeyStore = {
227
- get: jest.fn().mockReturnValue({
228
- toPEM: jest.fn().mockReturnValue('cached-pem-key')
229
- })
230
- };
231
- const jose = require('node-jose');
232
- jose.JWK.asKeyStore = jest.fn().mockResolvedValue(mockKeyStore);
233
- const testToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImtleS0xIn0.payload.signature';
234
- const result = await middleware.getPublicKeyFromCache(testToken);
235
- expect(mockAxios.get).not.toHaveBeenCalled(); // No HTTP call
236
- expect(result).toBe('cached-pem-key');
237
- });
238
- });
239
- });
240
- // Integration Tests
241
- describe('ProjectAuthMiddleware Integration Tests', () => {
242
- let middleware;
243
- let realRedis;
244
- beforeAll(async () => {
245
- // Use real Redis for integration tests (or Redis test container)
246
- process.env.REDIS_URL = process.env.TEST_REDIS_URL || 'redis://localhost:6380';
247
- process.env.MERCURY_BASE_URL = 'http://localhost:4000';
248
- process.env.SERVICE_ID = 'integration-test-service';
249
- });
250
- beforeEach(async () => {
251
- jest.restoreAllMocks();
252
- middleware = new middlewares_1.ProjectAuthMiddleware();
253
- // Clear Redis cache
254
- const { createClient } = require('redis');
255
- realRedis = createClient({ url: process.env.REDIS_URL });
256
- await realRedis.connect();
257
- await realRedis.flushAll();
258
- });
259
- afterEach(async () => {
260
- if (realRedis) {
261
- await realRedis.quit();
262
- }
263
- await middleware.cleanup();
264
- });
265
- it('should perform end-to-end authentication with real token', async () => {
266
- // This test requires:
267
- // 1. Mercury service running
268
- // 2. Valid project token generated
269
- // 3. Real Redis instance
270
- const realProjectToken = process.env.TEST_PROJECT_TOKEN;
271
- if (!realProjectToken) {
272
- console.warn('Skipping integration test - TEST_PROJECT_TOKEN not provided');
273
- return;
274
- }
275
- const mockReq = {
276
- headers: {
277
- 'x-project-token': `Bearer ${realProjectToken}`
278
- },
279
- project: undefined,
280
- get: jest.fn(),
281
- header: jest.fn(),
282
- params: {},
283
- query: {},
284
- body: {},
285
- url: '/',
286
- method: 'GET'
287
- };
288
- const mockRes = {
289
- status: jest.fn().mockReturnThis(),
290
- json: jest.fn().mockReturnThis(),
291
- send: jest.fn().mockReturnThis(),
292
- end: jest.fn().mockReturnThis()
293
- };
294
- const mockNext = jest.fn();
295
- await middleware.authenticate(mockReq);
296
- if (mockNext.mock.calls.length > 0) {
297
- // Authentication successful
298
- expect(mockReq.project).toBeDefined();
299
- expect(mockReq.project.project_uuid).toBeDefined();
300
- expect(mockReq.project.enabled_services).toBeInstanceOf(Array);
301
- }
302
- else {
303
- // Authentication failed - check response
304
- expect(mockRes.status).toHaveBeenCalledWith(expect.any(Number));
305
- }
306
- });
307
- it('should cache JWKS and reuse for subsequent requests', async () => {
308
- // Mock successful JWKS response
309
- const mockJwksResponse = {
310
- data: {
311
- keys: [
312
- {
313
- kid: 'test-key-1',
314
- kty: 'RSA',
315
- use: 'sig',
316
- n: 'mock-modulus',
317
- e: 'AQAB'
318
- }
319
- ]
320
- }
321
- };
322
- mockAxios.get.mockResolvedValue(mockJwksResponse);
323
- // First request should fetch JWKS
324
- const testToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InRlc3Qta2V5LTEifQ.payload.signature';
325
- try {
326
- await middleware.getPublicKeyFromCache(testToken);
327
- }
328
- catch (error) {
329
- // Expected to fail due to mocked JWT, but JWKS should be cached
330
- }
331
- // Verify JWKS was cached
332
- const cachedJwks = await realRedis.get('project_jwks_cache');
333
- expect(cachedJwks).toBeDefined();
334
- expect(JSON.parse(cachedJwks)).toEqual(mockJwksResponse.data);
335
- // Second request should use cache
336
- mockAxios.get.mockClear();
337
- try {
338
- await middleware.getPublicKeyFromCache(testToken);
339
- }
340
- catch (error) {
341
- // Expected to fail due to mocked JWT
342
- }
343
- // Should not have made another HTTP call
344
- expect(mockAxios.get).not.toHaveBeenCalled();
345
- });
346
- it('should handle Mercury service unavailable', async () => {
347
- mockAxios.get.mockRejectedValue({
348
- code: 'ECONNREFUSED',
349
- message: 'Connection refused'
350
- });
351
- const testToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InRlc3Qta2V5LTEifQ.payload.signature';
352
- await expect(middleware.getPublicKeyFromCache(testToken))
353
- .rejects
354
- .toThrow('Mercury service unavailable');
355
- });
356
- });
357
- // Performance Tests
358
- describe('ProjectAuthMiddleware Performance Tests', () => {
359
- let middleware;
360
- beforeAll(() => {
361
- middleware = new middlewares_1.ProjectAuthMiddleware();
362
- });
363
- it('should validate tokens within performance threshold', async () => {
364
- // Mock fast Redis responses
365
- mockRedis.sendCommand
366
- .mockResolvedValueOnce('cached-jwks') // JWKS cache hit
367
- .mockResolvedValueOnce(1); // Token exists
368
- const mockPayload = {
369
- project_uuid: 'perf-test',
370
- token_id: 'perf-token',
371
- enabled_services: ['test-service']
372
- };
373
- mockJwt.verify.mockReturnValue(mockPayload);
374
- const mockGetPublicKey = jest.spyOn(middleware, 'getPublicKeyFromCache');
375
- mockGetPublicKey.mockResolvedValue('mock-key');
376
- const startTime = Date.now();
377
- await middleware.validateProjectToken('test.token.here');
378
- const duration = Date.now() - startTime;
379
- // Should complete validation in under 50ms for cached scenarios
380
- expect(duration).toBeLessThan(50);
381
- });
382
- });
383
- //# sourceMappingURL=middleware.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"middleware.test.js","sourceRoot":"","sources":["../../src/test/middleware.test.ts"],"names":[],"mappings":"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"}