@globaltracking/auth-middleware 2.1.0 → 3.0.0
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/README.md +421 -372
- package/dist/nestjs/gt-auth.module.d.ts +22 -0
- package/dist/nestjs/gt-auth.module.d.ts.map +1 -1
- package/dist/nestjs/gt-auth.module.js +39 -28
- package/dist/nestjs/gt-auth.module.js.map +1 -1
- package/package.json +82 -82
package/README.md
CHANGED
|
@@ -1,372 +1,421 @@
|
|
|
1
|
-
# @globaltracking/auth-middleware
|
|
2
|
-
|
|
3
|
-
Unified authentication and authorization middleware for the **Global Tracking** platform. Shared by all backend microservices — supports both **Express** and **NestJS**.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Strategy pattern**: Gateway header, trusted headers, JWT — configurable per service
|
|
8
|
-
- **NestJS adapter**: `GtAuthModule`, guards, decorators, interceptors, exception filter
|
|
9
|
-
- **Express middleware**: `authenticate`, `requirePermission`, `requireRole`, `requireSelf`, `requireTenant`
|
|
10
|
-
- **Hybrid permission resolution**: JWT claims (fast) → custom resolver → RBAC HTTP call → deny (fail-closed)
|
|
11
|
-
- **Multi-tenant RLS**: `OrgContextInterceptor` sets `SET LOCAL app.current_org_id` for PostgreSQL Row-Level Security
|
|
12
|
-
- **Admin bypass**: Configurable `adminRoles[]` bypass all permission checks
|
|
13
|
-
- **TypeScript-first**: Full type definitions with Express `Request` augmentation
|
|
14
|
-
- **98%+ test coverage**: 89 tests across strategies, middlewares, and config
|
|
15
|
-
|
|
16
|
-
## Installation
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
npm install @globaltracking/auth-middleware
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
**Peer dependencies:**
|
|
23
|
-
|
|
24
|
-
| Package | Required for | Optional? |
|
|
25
|
-
|---------|-------------|-----------|
|
|
26
|
-
| `express` ^4.18 | Express middleware | Required |
|
|
27
|
-
| `@nestjs/common` ^11.0 | NestJS adapter | Optional |
|
|
28
|
-
| `@nestjs/core` ^11.0 | NestJS adapter | Optional |
|
|
29
|
-
| `typeorm` ^0.3.0 | OrgContextInterceptor (RLS) | Optional |
|
|
30
|
-
| `rxjs` ^7.0 | OrgContextInterceptor | Optional |
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## NestJS Integration (Recommended)
|
|
35
|
-
|
|
36
|
-
This is the primary integration path for Global Tracking microservices.
|
|
37
|
-
|
|
38
|
-
### 1. Import GtAuthModule in your AppModule
|
|
39
|
-
|
|
40
|
-
```typescript
|
|
41
|
-
import { Module } from '@nestjs/common';
|
|
42
|
-
import { ConfigService } from '@nestjs/config';
|
|
43
|
-
import { GtAuthModule } from '@globaltracking/auth-middleware/nestjs';
|
|
44
|
-
|
|
45
|
-
@Module({
|
|
46
|
-
imports: [
|
|
47
|
-
// ... ConfigModule, TypeOrmModule, ThrottlerModule ...
|
|
48
|
-
|
|
49
|
-
GtAuthModule.forRootAsync({
|
|
50
|
-
inject: [ConfigService],
|
|
51
|
-
useFactory: (config: ConfigService) => ({
|
|
52
|
-
strategies: ['trusted-headers'],
|
|
53
|
-
internalGatewayToken: config.get('INTERNAL_GATEWAY_TOKEN'),
|
|
54
|
-
adminRoles: ['system_admin', 'org_admin'],
|
|
55
|
-
rbacServiceUrl: config.get('RBAC_SERVICE_URL'),
|
|
56
|
-
}),
|
|
57
|
-
}),
|
|
58
|
-
|
|
59
|
-
// ... domain modules ...
|
|
60
|
-
],
|
|
61
|
-
})
|
|
62
|
-
export class AppModule {}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
**What `GtAuthModule` provides (globally):**
|
|
66
|
-
|
|
67
|
-
| Component | What it does |
|
|
68
|
-
|-----------|-------------|
|
|
69
|
-
| `GtTrustedHeadersMiddleware` | Extracts `req.user` from configured strategy chain (auto-applied to all routes) |
|
|
70
|
-
| `InternalOnlyGuard` | Validates `X-Gateway-Token` header — register as `APP_GUARD` |
|
|
71
|
-
| `GtPermissionsGuard` | Checks `@RequirePermissions()` —
|
|
72
|
-
| `OrgContextInterceptor` | Sets PostgreSQL RLS context — register as `APP_INTERCEPTOR` |
|
|
73
|
-
| `AuthExceptionFilter` | Catches `AuthError` and returns standard error envelope |
|
|
74
|
-
|
|
75
|
-
### 2. Use decorators in controllers
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
import {
|
|
79
|
-
RequirePermissions,
|
|
80
|
-
CurrentUser,
|
|
81
|
-
CurrentOrg,
|
|
82
|
-
Public,
|
|
83
|
-
RequireRoles,
|
|
84
|
-
} from '@globaltracking/auth-middleware/nestjs';
|
|
85
|
-
|
|
86
|
-
@Controller('vehicles')
|
|
87
|
-
export class VehiclesController {
|
|
88
|
-
@Post()
|
|
89
|
-
@RequirePermissions('vehicles:create')
|
|
90
|
-
create(
|
|
91
|
-
@CurrentOrg() orgId: string,
|
|
92
|
-
@CurrentUser('userId') userId: string,
|
|
93
|
-
@Body() dto: CreateVehicleDto,
|
|
94
|
-
) {
|
|
95
|
-
// orgId and userId extracted from trusted headers
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
@Get(':id')
|
|
99
|
-
@RequirePermissions('vehicles:read')
|
|
100
|
-
findOne(
|
|
101
|
-
@CurrentOrg() orgId: string,
|
|
102
|
-
@Param('id', ParseUUIDPipe) id: string,
|
|
103
|
-
) { ... }
|
|
104
|
-
|
|
105
|
-
@Delete(':id')
|
|
106
|
-
@RequireRoles('system_admin')
|
|
107
|
-
remove(@Param('id', ParseUUIDPipe) id: string) { ... }
|
|
108
|
-
}
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
```typescript
|
|
112
|
-
// Health endpoints skip auth
|
|
113
|
-
@Controller('health')
|
|
114
|
-
export class HealthController {
|
|
115
|
-
@Get()
|
|
116
|
-
@Public()
|
|
117
|
-
liveness() {
|
|
118
|
-
return { status: 'ok' };
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### 3. Register guards and interceptors
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
{ provide: APP_GUARD, useClass: ThrottlerGuard },
|
|
137
|
-
{ provide: APP_INTERCEPTOR, useClass: OrgContextInterceptor },
|
|
138
|
-
// ... your other interceptors
|
|
139
|
-
],
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
authenticate,
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
//
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
1
|
+
# @globaltracking/auth-middleware
|
|
2
|
+
|
|
3
|
+
Unified authentication and authorization middleware for the **Global Tracking** platform. Shared by all backend microservices — supports both **Express** and **NestJS**.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Strategy pattern**: Gateway header, trusted headers, JWT — configurable per service
|
|
8
|
+
- **NestJS adapter**: `GtAuthModule`, guards, decorators, interceptors, exception filter
|
|
9
|
+
- **Express middleware**: `authenticate`, `requirePermission`, `requireRole`, `requireSelf`, `requireTenant`
|
|
10
|
+
- **Hybrid permission resolution**: JWT claims (fast) → custom resolver → RBAC HTTP call → deny (fail-closed)
|
|
11
|
+
- **Multi-tenant RLS**: `OrgContextInterceptor` sets `SET LOCAL app.current_org_id` for PostgreSQL Row-Level Security
|
|
12
|
+
- **Admin bypass**: Configurable `adminRoles[]` bypass all permission checks
|
|
13
|
+
- **TypeScript-first**: Full type definitions with Express `Request` augmentation
|
|
14
|
+
- **98%+ test coverage**: 89 tests across strategies, middlewares, and config
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @globaltracking/auth-middleware
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Peer dependencies:**
|
|
23
|
+
|
|
24
|
+
| Package | Required for | Optional? |
|
|
25
|
+
|---------|-------------|-----------|
|
|
26
|
+
| `express` ^4.18 | Express middleware | Required |
|
|
27
|
+
| `@nestjs/common` ^11.0 | NestJS adapter | Optional |
|
|
28
|
+
| `@nestjs/core` ^11.0 | NestJS adapter | Optional |
|
|
29
|
+
| `typeorm` ^0.3.0 | OrgContextInterceptor (RLS) | Optional |
|
|
30
|
+
| `rxjs` ^7.0 | OrgContextInterceptor | Optional |
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## NestJS Integration (Recommended)
|
|
35
|
+
|
|
36
|
+
This is the primary integration path for Global Tracking microservices.
|
|
37
|
+
|
|
38
|
+
### 1. Import GtAuthModule in your AppModule
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { Module } from '@nestjs/common';
|
|
42
|
+
import { ConfigService } from '@nestjs/config';
|
|
43
|
+
import { GtAuthModule } from '@globaltracking/auth-middleware/nestjs';
|
|
44
|
+
|
|
45
|
+
@Module({
|
|
46
|
+
imports: [
|
|
47
|
+
// ... ConfigModule, TypeOrmModule, ThrottlerModule ...
|
|
48
|
+
|
|
49
|
+
GtAuthModule.forRootAsync({
|
|
50
|
+
inject: [ConfigService],
|
|
51
|
+
useFactory: (config: ConfigService) => ({
|
|
52
|
+
strategies: ['trusted-headers'],
|
|
53
|
+
internalGatewayToken: config.get('INTERNAL_GATEWAY_TOKEN'),
|
|
54
|
+
adminRoles: ['system_admin', 'org_admin'],
|
|
55
|
+
rbacServiceUrl: config.get('RBAC_SERVICE_URL'),
|
|
56
|
+
}),
|
|
57
|
+
}),
|
|
58
|
+
|
|
59
|
+
// ... domain modules ...
|
|
60
|
+
],
|
|
61
|
+
})
|
|
62
|
+
export class AppModule {}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**What `GtAuthModule` provides (globally):**
|
|
66
|
+
|
|
67
|
+
| Component | What it does |
|
|
68
|
+
|-----------|-------------|
|
|
69
|
+
| `GtTrustedHeadersMiddleware` | Extracts `req.user` from configured strategy chain (auto-applied to all routes) |
|
|
70
|
+
| `InternalOnlyGuard` | Validates `X-Gateway-Token` header — attach per-route with `@UseGuards()` or register as `APP_GUARD` |
|
|
71
|
+
| `GtPermissionsGuard` | Checks `@RequirePermissions()` — **auto-registered as `APP_GUARD` since v3** (opt out with `registerGuardGlobally: false`) |
|
|
72
|
+
| `OrgContextInterceptor` | Sets PostgreSQL RLS context — register as `APP_INTERCEPTOR` |
|
|
73
|
+
| `AuthExceptionFilter` | Catches `AuthError` and returns standard error envelope |
|
|
74
|
+
|
|
75
|
+
### 2. Use decorators in controllers
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import {
|
|
79
|
+
RequirePermissions,
|
|
80
|
+
CurrentUser,
|
|
81
|
+
CurrentOrg,
|
|
82
|
+
Public,
|
|
83
|
+
RequireRoles,
|
|
84
|
+
} from '@globaltracking/auth-middleware/nestjs';
|
|
85
|
+
|
|
86
|
+
@Controller('vehicles')
|
|
87
|
+
export class VehiclesController {
|
|
88
|
+
@Post()
|
|
89
|
+
@RequirePermissions('vehicles:create')
|
|
90
|
+
create(
|
|
91
|
+
@CurrentOrg() orgId: string,
|
|
92
|
+
@CurrentUser('userId') userId: string,
|
|
93
|
+
@Body() dto: CreateVehicleDto,
|
|
94
|
+
) {
|
|
95
|
+
// orgId and userId extracted from trusted headers
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@Get(':id')
|
|
99
|
+
@RequirePermissions('vehicles:read')
|
|
100
|
+
findOne(
|
|
101
|
+
@CurrentOrg() orgId: string,
|
|
102
|
+
@Param('id', ParseUUIDPipe) id: string,
|
|
103
|
+
) { ... }
|
|
104
|
+
|
|
105
|
+
@Delete(':id')
|
|
106
|
+
@RequireRoles('system_admin')
|
|
107
|
+
remove(@Param('id', ParseUUIDPipe) id: string) { ... }
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
// Health endpoints skip auth
|
|
113
|
+
@Controller('health')
|
|
114
|
+
export class HealthController {
|
|
115
|
+
@Get()
|
|
116
|
+
@Public()
|
|
117
|
+
liveness() {
|
|
118
|
+
return { status: 'ok' };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### 3. Register guards and interceptors
|
|
124
|
+
|
|
125
|
+
Since v3, `GtPermissionsGuard` is auto-registered as an `APP_GUARD` by
|
|
126
|
+
`GtAuthModule.forRoot()` / `forRootAsync()`. You only need to wire the
|
|
127
|
+
interceptor and any service-specific guards:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
// app.module.ts providers
|
|
131
|
+
import {
|
|
132
|
+
OrgContextInterceptor,
|
|
133
|
+
} from '@globaltracking/auth-middleware/nestjs';
|
|
134
|
+
|
|
135
|
+
providers: [
|
|
136
|
+
{ provide: APP_GUARD, useClass: ThrottlerGuard },
|
|
137
|
+
{ provide: APP_INTERCEPTOR, useClass: OrgContextInterceptor },
|
|
138
|
+
// ... your other interceptors
|
|
139
|
+
],
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Opt-out:** pass `registerGuardGlobally: false` if your service composes its
|
|
143
|
+
own guard chain and wants to attach `GtPermissionsGuard` manually:
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
GtAuthModule.forRootAsync({
|
|
147
|
+
registerGuardGlobally: false,
|
|
148
|
+
inject: [ConfigService],
|
|
149
|
+
useFactory: (c: ConfigService) => ({ ... }),
|
|
150
|
+
})
|
|
151
|
+
// then in providers:
|
|
152
|
+
{ provide: APP_GUARD, useClass: MyCompositeGuard }, // wraps Gt checks itself
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**`InternalOnlyGuard`** is not auto-registered — attach it per-route via
|
|
156
|
+
`@UseGuards(InternalOnlyGuard)` on internal-only endpoints, or register it
|
|
157
|
+
globally if *every* route in the service is internal-only.
|
|
158
|
+
|
|
159
|
+
### 4. Add env vars
|
|
160
|
+
|
|
161
|
+
```env
|
|
162
|
+
INTERNAL_GATEWAY_TOKEN=your-32-char-min-secret
|
|
163
|
+
RBAC_SERVICE_URL=http://gt-rbac-service:3000 # optional, for permission resolution
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Special case: gt-rbac-service
|
|
167
|
+
|
|
168
|
+
The RBAC service **cannot call itself** for permission resolution. Instead, inject its own `ResolveService` via `permissionResolver`:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
GtAuthModule.forRootAsync({
|
|
172
|
+
imports: [ResolveModule],
|
|
173
|
+
inject: [ConfigService, ResolveService],
|
|
174
|
+
useFactory: (config: ConfigService, resolveService: ResolveService) => ({
|
|
175
|
+
strategies: ['trusted-headers'],
|
|
176
|
+
internalGatewayToken: config.get('INTERNAL_GATEWAY_TOKEN'),
|
|
177
|
+
adminRoles: ['system_admin', 'org_admin'],
|
|
178
|
+
permissionResolver: (orgId, userId, resource, action) =>
|
|
179
|
+
resolveService.checkPermission(orgId, userId, resource, action),
|
|
180
|
+
}),
|
|
181
|
+
}),
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Express Integration
|
|
187
|
+
|
|
188
|
+
For services that use plain Express (no NestJS):
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
import express from 'express';
|
|
192
|
+
import {
|
|
193
|
+
initAuth,
|
|
194
|
+
authenticate,
|
|
195
|
+
requirePermission,
|
|
196
|
+
requireTenant,
|
|
197
|
+
authErrorHandler,
|
|
198
|
+
} from '@globaltracking/auth-middleware';
|
|
199
|
+
|
|
200
|
+
const app = express();
|
|
201
|
+
|
|
202
|
+
// Initialize once at startup
|
|
203
|
+
initAuth({
|
|
204
|
+
strategies: ['gateway-header', 'jwt'],
|
|
205
|
+
adminRoles: ['system_admin', 'org_admin'],
|
|
206
|
+
publicKeyPath: './keys/public.pem',
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Protected route
|
|
210
|
+
app.get('/v1/vehicles',
|
|
211
|
+
authenticate,
|
|
212
|
+
requireTenant,
|
|
213
|
+
requirePermission('vehicles:read'),
|
|
214
|
+
async (req, res) => {
|
|
215
|
+
// req.user.userId, req.user.orgId, etc.
|
|
216
|
+
// req.tenantId set by requireTenant
|
|
217
|
+
}
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
// Error handler (must be last)
|
|
221
|
+
app.use(authErrorHandler);
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Configuration
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
initAuth({
|
|
230
|
+
// Strategy chain — tried in order until one matches
|
|
231
|
+
strategies: ['gateway-header', 'jwt'], // default
|
|
232
|
+
|
|
233
|
+
// Gateway header name (GCP API Gateway)
|
|
234
|
+
gatewayHeaderName: 'x-apigateway-api-userinfo', // default
|
|
235
|
+
|
|
236
|
+
// JWT verification (for local dev / non-gateway)
|
|
237
|
+
jwtIssuer: 'globaltracking-auth', // default
|
|
238
|
+
publicKey: '-----BEGIN PUBLIC KEY-----\n...', // PEM string
|
|
239
|
+
publicKeyPath: './keys/public.pem', // or file path
|
|
240
|
+
|
|
241
|
+
// Roles that bypass all permission checks
|
|
242
|
+
adminRoles: ['system_admin', 'org_admin'], // default
|
|
243
|
+
|
|
244
|
+
// Trusted headers strategy config
|
|
245
|
+
internalGatewayToken: 'secret', // also reads env INTERNAL_GATEWAY_TOKEN
|
|
246
|
+
trustedHeaderNames: {
|
|
247
|
+
userId: 'x-user-id', // default
|
|
248
|
+
orgId: 'x-org-id', // default
|
|
249
|
+
userRole: 'x-user-role', // default
|
|
250
|
+
requestId: 'x-request-id', // default
|
|
251
|
+
gatewayToken: 'x-gateway-token', // default
|
|
252
|
+
},
|
|
253
|
+
|
|
254
|
+
// Permission resolution (NestJS GtPermissionsGuard)
|
|
255
|
+
rbacServiceUrl: 'http://gt-rbac-service:3000', // HTTP fallback
|
|
256
|
+
permissionResolver: async (orgId, userId, resource, action) => {
|
|
257
|
+
// Custom resolver (e.g., direct DB call)
|
|
258
|
+
return true;
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Public key resolution order: `publicKey` → `publicKeyPath` → `AUTH_PUBLIC_KEY` env → `AUTH_PUBLIC_KEY_PATH` env.
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Auth Strategies
|
|
268
|
+
|
|
269
|
+
| Strategy | When used | What it reads |
|
|
270
|
+
|----------|-----------|---------------|
|
|
271
|
+
| `gateway-header` | Production (GCP API Gateway) | Base64-encoded JSON in `X-Apigateway-Api-Userinfo` |
|
|
272
|
+
| `trusted-headers` | NestJS services behind API Gateway | `X-User-Id`, `X-Org-Id`, `X-User-Role`, `X-Request-Id`, `X-Gateway-Token` |
|
|
273
|
+
| `jwt` | Local dev, non-gateway environments | `Authorization: Bearer <token>` (RS256 verification) |
|
|
274
|
+
|
|
275
|
+
The strategy chain iterates in the configured order. The first strategy whose `canHandle(req)` returns true is used.
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## AuthUser Shape
|
|
280
|
+
|
|
281
|
+
Every authenticated request gets `req.user` populated with:
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
interface AuthUser {
|
|
285
|
+
userId: string; // from JWT sub or X-User-Id
|
|
286
|
+
email: string; // from JWT email (empty in trusted-headers mode)
|
|
287
|
+
role: UserRole; // from JWT role or X-User-Role
|
|
288
|
+
orgId: string; // from JWT org_id or X-Org-Id
|
|
289
|
+
tenantId: string; // = orgId in trusted-headers mode
|
|
290
|
+
permissions: string[]; // from JWT claims (empty in trusted-headers mode)
|
|
291
|
+
requestId: string; // from X-Request-Id
|
|
292
|
+
authSource: AuthStrategy; // 'gateway-header' | 'trusted-headers' | 'jwt'
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## Permission Resolution (GtPermissionsGuard)
|
|
299
|
+
|
|
300
|
+
The NestJS `GtPermissionsGuard` resolves permissions in 3 tiers:
|
|
301
|
+
|
|
302
|
+
1. **JWT claims** — If `user.permissions` is non-empty, check in-memory (fast path)
|
|
303
|
+
2. **permissionResolver** — If configured, call the function directly (for RBAC service)
|
|
304
|
+
3. **RBAC HTTP call** — If `rbacServiceUrl` is configured, POST to `/v1/resolve/check`
|
|
305
|
+
4. **Deny** — Fail-closed if no resolution mechanism is available
|
|
306
|
+
|
|
307
|
+
Admin roles (`config.adminRoles`) always bypass all checks.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## Express Middlewares
|
|
312
|
+
|
|
313
|
+
| Middleware | Purpose |
|
|
314
|
+
|-----------|---------|
|
|
315
|
+
| `authenticate` | Extracts `req.user` from strategy chain |
|
|
316
|
+
| `requireRole(...roles)` | Checks `req.user.role` against allowed roles |
|
|
317
|
+
| `requirePermission(...perms)` | Requires ALL listed permissions (admin bypass) |
|
|
318
|
+
| `requireAnyPermission(...perms)` | Requires AT LEAST ONE permission (admin bypass) |
|
|
319
|
+
| `requireTenant` | Ensures `req.user.tenantId` exists, sets `req.tenantId` |
|
|
320
|
+
| `requireSelf(paramName?)` | Compares `req.user.userId` with route param (admin bypass) |
|
|
321
|
+
| `authErrorHandler` | Error handler for `AuthError` subclasses |
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## Error Handling
|
|
326
|
+
|
|
327
|
+
All auth errors extend `AuthError` and produce the standard Global Tracking error envelope:
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
import { UnauthorizedError, ForbiddenError } from '@globaltracking/auth-middleware';
|
|
331
|
+
|
|
332
|
+
throw new UnauthorizedError('Token expired');
|
|
333
|
+
// → 401 { success: false, error: { code: 'UNAUTHORIZED', message: 'Token expired', statusCode: 401 } }
|
|
334
|
+
|
|
335
|
+
throw new ForbiddenError('Insufficient permissions', { required: ['vehicles:write'] });
|
|
336
|
+
// → 403 { success: false, error: { code: 'FORBIDDEN', message: 'Insufficient permissions', statusCode: 403 } }
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## Utility Functions
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
import { extractUser, hasRole, hasPermission, hasAnyPermission } from '@globaltracking/auth-middleware';
|
|
345
|
+
|
|
346
|
+
const user = extractUser(req); // throws UnauthorizedError if missing
|
|
347
|
+
hasRole(user, 'system_admin'); // boolean
|
|
348
|
+
hasPermission(user, 'vehicles:read'); // all must match
|
|
349
|
+
hasAnyPermission(user, 'a:read', 'b:read'); // at least one
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## Files Replaced Per Service
|
|
355
|
+
|
|
356
|
+
When a NestJS service adopts this package, these ~10 files can be deleted:
|
|
357
|
+
|
|
358
|
+
```
|
|
359
|
+
src/common/decorators/current-org.decorator.ts → @CurrentOrg from package
|
|
360
|
+
src/common/decorators/current-user.decorator.ts → @CurrentUser from package
|
|
361
|
+
src/common/decorators/permissions.decorator.ts → @RequirePermissions from package
|
|
362
|
+
src/common/decorators/public.decorator.ts → @Public from package
|
|
363
|
+
src/common/guards/internal-only.guard.ts → InternalOnlyGuard from package
|
|
364
|
+
src/common/guards/permissions.guard.ts → GtPermissionsGuard from package
|
|
365
|
+
src/common/interceptors/org-context.interceptor.ts → OrgContextInterceptor from package
|
|
366
|
+
src/common/middleware/trusted-headers.middleware.ts → GtTrustedHeadersMiddleware from package
|
|
367
|
+
src/common/interfaces/jwt-payload.interface.ts → AuthUser from package
|
|
368
|
+
src/common/interfaces/request-context.interface.ts → (Express augmentation from package)
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Development
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
npm test # run tests with coverage (89 tests, 98%+ coverage)
|
|
377
|
+
npm run test:watch # watch mode
|
|
378
|
+
npm run build # compile to dist/
|
|
379
|
+
npm run clean # remove dist/
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## Migration from v2.x → v3.0
|
|
385
|
+
|
|
386
|
+
**Breaking:** `GtAuthModule.forRoot()` / `forRootAsync()` now auto-registers
|
|
387
|
+
`GtPermissionsGuard` as an `APP_GUARD`. In v2.x the guard was `provided` but
|
|
388
|
+
never globally registered, which meant every `@RequirePermissions()`
|
|
389
|
+
decorator was silently inert (routes returned 2xx for users who lacked the
|
|
390
|
+
declared permission — a platform-wide security defect).
|
|
391
|
+
|
|
392
|
+
**What you need to do:**
|
|
393
|
+
|
|
394
|
+
1. **Remove** any existing `{ provide: APP_GUARD, useClass: GtPermissionsGuard }`
|
|
395
|
+
line from your service's `app.module.ts` — the library now registers it
|
|
396
|
+
for you. Leaving it in place only double-runs the guard (still correct,
|
|
397
|
+
just wasteful).
|
|
398
|
+
|
|
399
|
+
2. **Audit for endpoints that were accidentally working without the correct
|
|
400
|
+
permission**. Any route missing the right `@RequirePermissions(...)`
|
|
401
|
+
decorator will start returning 403 to non-admin users. Grep for missing
|
|
402
|
+
decorators on controllers that use other guards already; add the
|
|
403
|
+
decorator or annotate with `@Public()` as appropriate.
|
|
404
|
+
|
|
405
|
+
3. **If your service composes its own guard chain** (e.g. gt-alert-engine's
|
|
406
|
+
custom `GatewayAuthGuard`/`OrgIdGuard` stack) and you do not want the
|
|
407
|
+
automatic registration, pass `registerGuardGlobally: false`:
|
|
408
|
+
|
|
409
|
+
```typescript
|
|
410
|
+
GtAuthModule.forRootAsync({
|
|
411
|
+
registerGuardGlobally: false,
|
|
412
|
+
...
|
|
413
|
+
})
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
## Migration from v1.x
|
|
417
|
+
|
|
418
|
+
- `superAdminRole` → use `adminRoles: ['system_admin', 'org_admin']` (legacy `superAdminRole` still works)
|
|
419
|
+
- `RequestUser` type alias still exported for backward compatibility
|
|
420
|
+
- Error handler now returns `{ success: false, error: { code, message, statusCode } }` envelope instead of `{ error: message }`
|
|
421
|
+
- `extractUser()` now sets `authSource` and `requestId` on returned user
|
|
@@ -1,11 +1,33 @@
|
|
|
1
1
|
import { DynamicModule, MiddlewareConsumer, NestModule } from '@nestjs/common';
|
|
2
2
|
import { AuthConfig } from '../types';
|
|
3
3
|
export interface GtAuthModuleOptions extends AuthConfig {
|
|
4
|
+
/**
|
|
5
|
+
* Auto-register `GtPermissionsGuard` as an APP_GUARD so that every
|
|
6
|
+
* `@RequirePermissions(...)` decorator is actually enforced. Default: `true`.
|
|
7
|
+
*
|
|
8
|
+
* Set to `false` only if your service wires its own guard chain (e.g. a
|
|
9
|
+
* custom gateway guard that composes multiple checks) and you want to
|
|
10
|
+
* attach `GtPermissionsGuard` manually via `@UseGuards()` or your own
|
|
11
|
+
* `APP_GUARD` binding.
|
|
12
|
+
*
|
|
13
|
+
* Historical note: before v3 this was effectively `false` — the guard was
|
|
14
|
+
* `provided` but never registered — which meant every `@RequirePermissions`
|
|
15
|
+
* decorator was inert metadata. Auto-registration is the new default so
|
|
16
|
+
* "permission is declared" implies "permission is enforced".
|
|
17
|
+
*/
|
|
18
|
+
registerGuardGlobally?: boolean;
|
|
4
19
|
}
|
|
5
20
|
export interface GtAuthModuleAsyncOptions {
|
|
6
21
|
imports?: any[];
|
|
7
22
|
inject?: any[];
|
|
8
23
|
useFactory: (...args: any[]) => GtAuthModuleOptions | Promise<GtAuthModuleOptions>;
|
|
24
|
+
/**
|
|
25
|
+
* Same semantics as `GtAuthModuleOptions.registerGuardGlobally`. Declared
|
|
26
|
+
* here (not on the factory return value) because module providers must be
|
|
27
|
+
* known at module-construction time, before the async factory has run.
|
|
28
|
+
* Default: `true`.
|
|
29
|
+
*/
|
|
30
|
+
registerGuardGlobally?: boolean;
|
|
9
31
|
}
|
|
10
32
|
/**
|
|
11
33
|
* NestJS dynamic module for Global Tracking authentication and authorization.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gt-auth.module.d.ts","sourceRoot":"","sources":["../../src/nestjs/gt-auth.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAU,UAAU,
|
|
1
|
+
{"version":3,"file":"gt-auth.module.d.ts","sourceRoot":"","sources":["../../src/nestjs/gt-auth.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAU,UAAU,EAAY,MAAM,gBAAgB,CAAC;AAEjG,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAUtC,MAAM,WAAW,mBAAoB,SAAQ,UAAU;IACrD;;;;;;;;;;;;;OAaG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC;IACf,UAAU,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACnF;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBACa,YAAa,YAAW,UAAU;IAC7C,SAAS,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI;IAI7C,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,mBAAwB,GAAG,aAAa;IAmChE,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,wBAAwB,GAAG,aAAa;CAuCtE"}
|
|
@@ -9,6 +9,7 @@ var GtAuthModule_1;
|
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.GtAuthModule = void 0;
|
|
11
11
|
const common_1 = require("@nestjs/common");
|
|
12
|
+
const core_1 = require("@nestjs/core");
|
|
12
13
|
const config_1 = require("../config");
|
|
13
14
|
const constants_1 = require("./constants");
|
|
14
15
|
const trusted_headers_middleware_1 = require("./middleware/trusted-headers.middleware");
|
|
@@ -38,21 +39,26 @@ let GtAuthModule = GtAuthModule_1 = class GtAuthModule {
|
|
|
38
39
|
consumer.apply(trusted_headers_middleware_1.GtTrustedHeadersMiddleware).forRoutes('*');
|
|
39
40
|
}
|
|
40
41
|
static forRoot(options = {}) {
|
|
41
|
-
|
|
42
|
+
const { registerGuardGlobally = true, ...authConfig } = options;
|
|
43
|
+
(0, config_1.initAuth)(authConfig);
|
|
44
|
+
const providers = [
|
|
45
|
+
{
|
|
46
|
+
provide: constants_1.GT_AUTH_CONFIG,
|
|
47
|
+
useFactory: () => (0, config_1.getConfig)(),
|
|
48
|
+
},
|
|
49
|
+
internal_only_guard_1.InternalOnlyGuard,
|
|
50
|
+
permissions_guard_1.GtPermissionsGuard,
|
|
51
|
+
auth_guard_1.GtAuthGuard,
|
|
52
|
+
org_context_interceptor_1.OrgContextInterceptor,
|
|
53
|
+
auth_exception_filter_1.AuthExceptionFilter,
|
|
54
|
+
];
|
|
55
|
+
if (registerGuardGlobally) {
|
|
56
|
+
providers.push({ provide: core_1.APP_GUARD, useClass: permissions_guard_1.GtPermissionsGuard });
|
|
57
|
+
}
|
|
42
58
|
return {
|
|
43
59
|
module: GtAuthModule_1,
|
|
44
60
|
global: true,
|
|
45
|
-
providers
|
|
46
|
-
{
|
|
47
|
-
provide: constants_1.GT_AUTH_CONFIG,
|
|
48
|
-
useFactory: () => (0, config_1.getConfig)(),
|
|
49
|
-
},
|
|
50
|
-
internal_only_guard_1.InternalOnlyGuard,
|
|
51
|
-
permissions_guard_1.GtPermissionsGuard,
|
|
52
|
-
auth_guard_1.GtAuthGuard,
|
|
53
|
-
org_context_interceptor_1.OrgContextInterceptor,
|
|
54
|
-
auth_exception_filter_1.AuthExceptionFilter,
|
|
55
|
-
],
|
|
61
|
+
providers,
|
|
56
62
|
exports: [
|
|
57
63
|
constants_1.GT_AUTH_CONFIG,
|
|
58
64
|
internal_only_guard_1.InternalOnlyGuard,
|
|
@@ -64,26 +70,31 @@ let GtAuthModule = GtAuthModule_1 = class GtAuthModule {
|
|
|
64
70
|
};
|
|
65
71
|
}
|
|
66
72
|
static forRootAsync(options) {
|
|
73
|
+
const { registerGuardGlobally = true } = options;
|
|
74
|
+
const providers = [
|
|
75
|
+
{
|
|
76
|
+
provide: constants_1.GT_AUTH_CONFIG,
|
|
77
|
+
useFactory: async (...args) => {
|
|
78
|
+
const config = await options.useFactory(...args);
|
|
79
|
+
(0, config_1.initAuth)(config);
|
|
80
|
+
return (0, config_1.getConfig)();
|
|
81
|
+
},
|
|
82
|
+
inject: options.inject || [],
|
|
83
|
+
},
|
|
84
|
+
internal_only_guard_1.InternalOnlyGuard,
|
|
85
|
+
permissions_guard_1.GtPermissionsGuard,
|
|
86
|
+
auth_guard_1.GtAuthGuard,
|
|
87
|
+
org_context_interceptor_1.OrgContextInterceptor,
|
|
88
|
+
auth_exception_filter_1.AuthExceptionFilter,
|
|
89
|
+
];
|
|
90
|
+
if (registerGuardGlobally) {
|
|
91
|
+
providers.push({ provide: core_1.APP_GUARD, useClass: permissions_guard_1.GtPermissionsGuard });
|
|
92
|
+
}
|
|
67
93
|
return {
|
|
68
94
|
module: GtAuthModule_1,
|
|
69
95
|
global: true,
|
|
70
96
|
imports: options.imports || [],
|
|
71
|
-
providers
|
|
72
|
-
{
|
|
73
|
-
provide: constants_1.GT_AUTH_CONFIG,
|
|
74
|
-
useFactory: async (...args) => {
|
|
75
|
-
const config = await options.useFactory(...args);
|
|
76
|
-
(0, config_1.initAuth)(config);
|
|
77
|
-
return (0, config_1.getConfig)();
|
|
78
|
-
},
|
|
79
|
-
inject: options.inject || [],
|
|
80
|
-
},
|
|
81
|
-
internal_only_guard_1.InternalOnlyGuard,
|
|
82
|
-
permissions_guard_1.GtPermissionsGuard,
|
|
83
|
-
auth_guard_1.GtAuthGuard,
|
|
84
|
-
org_context_interceptor_1.OrgContextInterceptor,
|
|
85
|
-
auth_exception_filter_1.AuthExceptionFilter,
|
|
86
|
-
],
|
|
97
|
+
providers,
|
|
87
98
|
exports: [
|
|
88
99
|
constants_1.GT_AUTH_CONFIG,
|
|
89
100
|
internal_only_guard_1.InternalOnlyGuard,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gt-auth.module.js","sourceRoot":"","sources":["../../src/nestjs/gt-auth.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"gt-auth.module.js","sourceRoot":"","sources":["../../src/nestjs/gt-auth.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAiG;AACjG,uCAAyC;AAEzC,sCAAgD;AAChD,2CAA6C;AAC7C,wFAAqF;AACrF,sEAAiE;AACjE,kEAAgE;AAChE,oDAAkD;AAClD,oFAA+E;AAC/E,2EAAsE;AAiCtE;;;;;;;;;;;;;;;GAeG;AAEI,IAAM,YAAY,oBAAlB,MAAM,YAAY;IACvB,SAAS,CAAC,QAA4B;QACpC,QAAQ,CAAC,KAAK,CAAC,uDAA0B,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,UAA+B,EAAE;QAC9C,MAAM,EAAE,qBAAqB,GAAG,IAAI,EAAE,GAAG,UAAU,EAAE,GAAG,OAAO,CAAC;QAChE,IAAA,iBAAQ,EAAC,UAAU,CAAC,CAAC;QAErB,MAAM,SAAS,GAAe;YAC5B;gBACE,OAAO,EAAE,0BAAc;gBACvB,UAAU,EAAE,GAAG,EAAE,CAAC,IAAA,kBAAS,GAAE;aAC9B;YACD,uCAAiB;YACjB,sCAAkB;YAClB,wBAAW;YACX,+CAAqB;YACrB,2CAAmB;SACpB,CAAC;QAEF,IAAI,qBAAqB,EAAE,CAAC;YAC1B,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,gBAAS,EAAE,QAAQ,EAAE,sCAAkB,EAAE,CAAC,CAAC;QACvE,CAAC;QAED,OAAO;YACL,MAAM,EAAE,cAAY;YACpB,MAAM,EAAE,IAAI;YACZ,SAAS;YACT,OAAO,EAAE;gBACP,0BAAc;gBACd,uCAAiB;gBACjB,sCAAkB;gBAClB,wBAAW;gBACX,+CAAqB;gBACrB,2CAAmB;aACpB;SACF,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,YAAY,CAAC,OAAiC;QACnD,MAAM,EAAE,qBAAqB,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;QAEjD,MAAM,SAAS,GAAe;YAC5B;gBACE,OAAO,EAAE,0BAAc;gBACvB,UAAU,EAAE,KAAK,EAAE,GAAG,IAAW,EAAE,EAAE;oBACnC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,CAAC;oBACjD,IAAA,iBAAQ,EAAC,MAAM,CAAC,CAAC;oBACjB,OAAO,IAAA,kBAAS,GAAE,CAAC;gBACrB,CAAC;gBACD,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;aAC7B;YACD,uCAAiB;YACjB,sCAAkB;YAClB,wBAAW;YACX,+CAAqB;YACrB,2CAAmB;SACpB,CAAC;QAEF,IAAI,qBAAqB,EAAE,CAAC;YAC1B,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,gBAAS,EAAE,QAAQ,EAAE,sCAAkB,EAAE,CAAC,CAAC;QACvE,CAAC;QAED,OAAO;YACL,MAAM,EAAE,cAAY;YACpB,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;YAC9B,SAAS;YACT,OAAO,EAAE;gBACP,0BAAc;gBACd,uCAAiB;gBACjB,sCAAkB;gBAClB,wBAAW;gBACX,+CAAqB;gBACrB,2CAAmB;aACpB;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AA/EY,oCAAY;uBAAZ,YAAY;IADxB,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,YAAY,CA+ExB"}
|
package/package.json
CHANGED
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@globaltracking/auth-middleware",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Unified authentication and authorization middleware for the Global Tracking platform (Express + NestJS)",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"exports": {
|
|
8
|
-
".": {
|
|
9
|
-
"types": "./dist/index.d.ts",
|
|
10
|
-
"default": "./dist/index.js"
|
|
11
|
-
},
|
|
12
|
-
"./nestjs": {
|
|
13
|
-
"types": "./dist/nestjs.d.ts",
|
|
14
|
-
"default": "./dist/nestjs.js"
|
|
15
|
-
}
|
|
16
|
-
},
|
|
17
|
-
"files": [
|
|
18
|
-
"dist"
|
|
19
|
-
],
|
|
20
|
-
"scripts": {
|
|
21
|
-
"build": "tsc -p tsconfig.build.json",
|
|
22
|
-
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
23
|
-
"prebuild": "npm run clean",
|
|
24
|
-
"test": "jest --coverage",
|
|
25
|
-
"test:watch": "jest --watch",
|
|
26
|
-
"prepublishOnly": "npm run build"
|
|
27
|
-
},
|
|
28
|
-
"keywords": [
|
|
29
|
-
"globaltracking",
|
|
30
|
-
"auth",
|
|
31
|
-
"middleware",
|
|
32
|
-
"express",
|
|
33
|
-
"nestjs",
|
|
34
|
-
"rbac",
|
|
35
|
-
"multi-tenant",
|
|
36
|
-
"jwt",
|
|
37
|
-
"rls"
|
|
38
|
-
],
|
|
39
|
-
"author": "GeoSentry",
|
|
40
|
-
"license": "UNLICENSED",
|
|
41
|
-
"repository": {
|
|
42
|
-
"type": "git",
|
|
43
|
-
"url": "https://github.com/TrackCongoInfra/gt-auth-middleware.git"
|
|
44
|
-
},
|
|
45
|
-
"publishConfig": {
|
|
46
|
-
"registry": "https://registry.npmjs.org",
|
|
47
|
-
"access": "public"
|
|
48
|
-
},
|
|
49
|
-
"peerDependencies": {
|
|
50
|
-
"express": "^4.18.0",
|
|
51
|
-
"@nestjs/common": "^11.0.0",
|
|
52
|
-
"@nestjs/core": "^11.0.0",
|
|
53
|
-
"typeorm": "^0.3.0",
|
|
54
|
-
"rxjs": "^7.0.0"
|
|
55
|
-
},
|
|
56
|
-
"peerDependenciesMeta": {
|
|
57
|
-
"@nestjs/common": { "optional": true },
|
|
58
|
-
"@nestjs/core": { "optional": true },
|
|
59
|
-
"typeorm": { "optional": true },
|
|
60
|
-
"rxjs": { "optional": true }
|
|
61
|
-
},
|
|
62
|
-
"dependencies": {
|
|
63
|
-
"jsonwebtoken": "^9.0.2"
|
|
64
|
-
},
|
|
65
|
-
"devDependencies": {
|
|
66
|
-
"@nestjs/common": "^11.1.18",
|
|
67
|
-
"@nestjs/core": "^11.1.18",
|
|
68
|
-
"@nestjs/testing": "^11.1.18",
|
|
69
|
-
"@types/express": "^4.17.21",
|
|
70
|
-
"@types/jest": "^29.5.14",
|
|
71
|
-
"@types/jsonwebtoken": "^9.0.9",
|
|
72
|
-
"@types/node": "^22.0.0",
|
|
73
|
-
"express": "^4.21.0",
|
|
74
|
-
"jest": "^29.7.0",
|
|
75
|
-
"reflect-metadata": "^0.2.2",
|
|
76
|
-
"rxjs": "^7.8.2",
|
|
77
|
-
"ts-jest": "^29.2.5",
|
|
78
|
-
"ts-node": "^10.9.2",
|
|
79
|
-
"typeorm": "^0.3.28",
|
|
80
|
-
"typescript": "^5.7.3"
|
|
81
|
-
}
|
|
82
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@globaltracking/auth-middleware",
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "Unified authentication and authorization middleware for the Global Tracking platform (Express + NestJS)",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./nestjs": {
|
|
13
|
+
"types": "./dist/nestjs.d.ts",
|
|
14
|
+
"default": "./dist/nestjs.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc -p tsconfig.build.json",
|
|
22
|
+
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
23
|
+
"prebuild": "npm run clean",
|
|
24
|
+
"test": "jest --coverage",
|
|
25
|
+
"test:watch": "jest --watch",
|
|
26
|
+
"prepublishOnly": "npm run build"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"globaltracking",
|
|
30
|
+
"auth",
|
|
31
|
+
"middleware",
|
|
32
|
+
"express",
|
|
33
|
+
"nestjs",
|
|
34
|
+
"rbac",
|
|
35
|
+
"multi-tenant",
|
|
36
|
+
"jwt",
|
|
37
|
+
"rls"
|
|
38
|
+
],
|
|
39
|
+
"author": "GeoSentry",
|
|
40
|
+
"license": "UNLICENSED",
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "https://github.com/TrackCongoInfra/gt-auth-middleware.git"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"registry": "https://registry.npmjs.org",
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"express": "^4.18.0",
|
|
51
|
+
"@nestjs/common": "^11.0.0",
|
|
52
|
+
"@nestjs/core": "^11.0.0",
|
|
53
|
+
"typeorm": "^0.3.0",
|
|
54
|
+
"rxjs": "^7.0.0"
|
|
55
|
+
},
|
|
56
|
+
"peerDependenciesMeta": {
|
|
57
|
+
"@nestjs/common": { "optional": true },
|
|
58
|
+
"@nestjs/core": { "optional": true },
|
|
59
|
+
"typeorm": { "optional": true },
|
|
60
|
+
"rxjs": { "optional": true }
|
|
61
|
+
},
|
|
62
|
+
"dependencies": {
|
|
63
|
+
"jsonwebtoken": "^9.0.2"
|
|
64
|
+
},
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"@nestjs/common": "^11.1.18",
|
|
67
|
+
"@nestjs/core": "^11.1.18",
|
|
68
|
+
"@nestjs/testing": "^11.1.18",
|
|
69
|
+
"@types/express": "^4.17.21",
|
|
70
|
+
"@types/jest": "^29.5.14",
|
|
71
|
+
"@types/jsonwebtoken": "^9.0.9",
|
|
72
|
+
"@types/node": "^22.0.0",
|
|
73
|
+
"express": "^4.21.0",
|
|
74
|
+
"jest": "^29.7.0",
|
|
75
|
+
"reflect-metadata": "^0.2.2",
|
|
76
|
+
"rxjs": "^7.8.2",
|
|
77
|
+
"ts-jest": "^29.2.5",
|
|
78
|
+
"ts-node": "^10.9.2",
|
|
79
|
+
"typeorm": "^0.3.28",
|
|
80
|
+
"typescript": "^5.7.3"
|
|
81
|
+
}
|
|
82
|
+
}
|