@ambushsoftworks/nestjs-auth-graphql 0.6.7 → 0.8.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 +205 -2
- package/dist/auth.module.d.ts +12 -2
- package/dist/auth.module.d.ts.map +1 -1
- package/dist/auth.module.js +38 -0
- package/dist/auth.module.js.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +2 -1
- package/dist/constants.js.map +1 -1
- package/dist/decorators/current-realm.decorator.d.ts +2 -0
- package/dist/decorators/current-realm.decorator.d.ts.map +1 -0
- package/dist/decorators/current-realm.decorator.js +10 -0
- package/dist/decorators/current-realm.decorator.js.map +1 -0
- package/dist/dto/jwt-payload.interface.d.ts +1 -0
- package/dist/dto/jwt-payload.interface.d.ts.map +1 -1
- package/dist/exceptions/invalid-auth-config.exception.d.ts +4 -0
- package/dist/exceptions/invalid-auth-config.exception.d.ts.map +1 -0
- package/dist/exceptions/invalid-auth-config.exception.js +12 -0
- package/dist/exceptions/invalid-auth-config.exception.js.map +1 -0
- package/dist/guards/tenant.guard.d.ts.map +1 -1
- package/dist/guards/tenant.guard.js +9 -1
- package/dist/guards/tenant.guard.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces/auth-logger.interface.d.ts +2 -0
- package/dist/interfaces/auth-logger.interface.d.ts.map +1 -1
- package/dist/interfaces/auth-logger.interface.js +2 -0
- package/dist/interfaces/auth-logger.interface.js.map +1 -1
- package/dist/interfaces/brute-force-repository.interface.d.ts +1 -0
- package/dist/interfaces/brute-force-repository.interface.d.ts.map +1 -1
- package/dist/interfaces/jwt-payload-factory.interface.d.ts +1 -0
- package/dist/interfaces/jwt-payload-factory.interface.d.ts.map +1 -1
- package/dist/interfaces/realm-extractor.interface.d.ts +4 -0
- package/dist/interfaces/realm-extractor.interface.d.ts.map +1 -0
- package/dist/interfaces/realm-extractor.interface.js +3 -0
- package/dist/interfaces/realm-extractor.interface.js.map +1 -0
- package/dist/interfaces/tenant-extractor.interface.d.ts +1 -1
- package/dist/interfaces/tenant-extractor.interface.d.ts.map +1 -1
- package/dist/interfaces/user-repository.interface.d.ts +6 -5
- package/dist/interfaces/user-repository.interface.d.ts.map +1 -1
- package/dist/middleware/realm.middleware.d.ts +9 -0
- package/dist/middleware/realm.middleware.d.ts.map +1 -0
- package/dist/middleware/realm.middleware.js +51 -0
- package/dist/middleware/realm.middleware.js.map +1 -0
- package/dist/repositories/noop-brute-force.repository.d.ts +1 -0
- package/dist/repositories/noop-brute-force.repository.d.ts.map +1 -1
- package/dist/repositories/noop-brute-force.repository.js +4 -0
- package/dist/repositories/noop-brute-force.repository.js.map +1 -1
- package/dist/resolvers/base-auth.resolver.d.ts +4 -3
- package/dist/resolvers/base-auth.resolver.d.ts.map +1 -1
- package/dist/resolvers/base-auth.resolver.js +24 -12
- package/dist/resolvers/base-auth.resolver.js.map +1 -1
- package/dist/resolvers/oauth.controller.d.ts.map +1 -1
- package/dist/resolvers/oauth.controller.js +7 -4
- package/dist/resolvers/oauth.controller.js.map +1 -1
- package/dist/services/auth.service.d.ts +16 -10
- package/dist/services/auth.service.d.ts.map +1 -1
- package/dist/services/auth.service.js +67 -48
- package/dist/services/auth.service.js.map +1 -1
- package/dist/services/brute-force-protection.service.d.ts +14 -7
- package/dist/services/brute-force-protection.service.d.ts.map +1 -1
- package/dist/services/brute-force-protection.service.js +68 -14
- package/dist/services/brute-force-protection.service.js.map +1 -1
- package/dist/services/default-jwt-payload-factory.d.ts +1 -0
- package/dist/services/default-jwt-payload-factory.d.ts.map +1 -1
- package/dist/services/default-jwt-payload-factory.js +5 -1
- package/dist/services/default-jwt-payload-factory.js.map +1 -1
- package/dist/services/verification.service.d.ts +7 -7
- package/dist/services/verification.service.d.ts.map +1 -1
- package/dist/services/verification.service.js +17 -17
- package/dist/services/verification.service.js.map +1 -1
- package/dist/strategies/jwt.strategy.d.ts +3 -1
- package/dist/strategies/jwt.strategy.d.ts.map +1 -1
- package/dist/strategies/jwt.strategy.js +10 -1
- package/dist/strategies/jwt.strategy.js.map +1 -1
- package/dist/test-utils/mock-repositories.d.ts.map +1 -1
- package/dist/test-utils/mock-repositories.js +1 -0
- package/dist/test-utils/mock-repositories.js.map +1 -1
- package/dist/utils/ip-hash.d.ts +2 -0
- package/dist/utils/ip-hash.d.ts.map +1 -0
- package/dist/utils/ip-hash.js +11 -0
- package/dist/utils/ip-hash.js.map +1 -0
- package/examples/full-resolver-template.ts +305 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @ambushsoftworks/nestjs-auth-graphql
|
|
2
2
|
|
|
3
|
-
Production-grade authentication module for NestJS GraphQL + REST APIs. JWT, cookie auth, multi-tenancy, OAuth, email verification, and more -- with zero database coupling.
|
|
3
|
+
Production-grade authentication module for NestJS GraphQL + REST APIs. JWT, cookie auth, multi-tenancy, realm-based identity isolation, OAuth, email verification, and more -- with zero database coupling.
|
|
4
4
|
|
|
5
5
|
## Table of Contents
|
|
6
6
|
|
|
@@ -11,6 +11,7 @@ Production-grade authentication module for NestJS GraphQL + REST APIs. JWT, cook
|
|
|
11
11
|
- [Features](#features)
|
|
12
12
|
- [Cookie Authentication](#cookie-authentication)
|
|
13
13
|
- [Multi-Tenancy](#multi-tenancy)
|
|
14
|
+
- [Realm-Based Identity Isolation](#realm-based-identity-isolation)
|
|
14
15
|
- [API Key Authentication](#api-key-authentication)
|
|
15
16
|
- [Email System](#email-system)
|
|
16
17
|
- [Verification Modes](#verification-modes)
|
|
@@ -206,6 +207,8 @@ TypeScript decorator metadata is not preserved when importing from compiled npm
|
|
|
206
207
|
|
|
207
208
|
When cookie auth is enabled, pass the GraphQL `context` so tokens are set as HttpOnly cookies. The response body will contain empty strings for `accessToken`/`refreshToken`.
|
|
208
209
|
|
|
210
|
+
**Reference template:** `examples/full-resolver-template.ts` ships in the published package and covers every `perform*` method with copy-paste-ready `@Mutation`/`@Query` decorators, `@Throttle` on auth-sensitive endpoints, and `@UseGuards(JwtAuthGuard)` on authenticated routes. It also demonstrates the `changePassword` + `issueAuthSession` keep-alive pattern. Each `perform*` method on `BaseAuthResolver` also has a method-specific JSDoc snippet you can lift directly.
|
|
211
|
+
|
|
209
212
|
### Available `perform*()` methods
|
|
210
213
|
|
|
211
214
|
**Authentication:**
|
|
@@ -363,6 +366,8 @@ const extractor = new HeaderTenantExtractor();
|
|
|
363
366
|
const extractor = new HeaderTenantExtractor('x-org-id');
|
|
364
367
|
```
|
|
365
368
|
|
|
369
|
+
`extractTenantId` may also return `Promise<string | null>`. `TenantGuard` awaits the result with no microtask overhead for sync returns. Async throws and rejected Promises are treated identically to a sync `null` return — the request is rejected with `400 Bad Request` and the internal cause is logged via Nest's `Logger` (never leaked to the client).
|
|
370
|
+
|
|
366
371
|
**Access tenant context** in resolvers:
|
|
367
372
|
|
|
368
373
|
```typescript
|
|
@@ -397,6 +402,100 @@ For resource-scoped permissions, combine with `@ResourceScope()` and provide an
|
|
|
397
402
|
async updateClient(@Args('clientId') clientId: string) { /* ... */ }
|
|
398
403
|
```
|
|
399
404
|
|
|
405
|
+
### Realm-Based Identity Isolation
|
|
406
|
+
|
|
407
|
+
Realms partition the user identity space so that users in one realm are completely invisible to another. The same email address can exist independently in different realms, each with its own password, tokens, and verification state. This is useful for white-label platforms, multi-brand businesses, and franchise systems.
|
|
408
|
+
|
|
409
|
+
Realms are opt-in: provide a `realmExtractorInstance` in `AuthModuleOptions`. No separate feature flag is needed. When not provided, everything works exactly as before.
|
|
410
|
+
|
|
411
|
+
**Implement `IRealmExtractor`:**
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
import { Injectable } from '@nestjs/common';
|
|
415
|
+
import { IRealmExtractor } from '@ambushsoftworks/nestjs-auth-graphql';
|
|
416
|
+
|
|
417
|
+
@Injectable()
|
|
418
|
+
export class HostnameRealmExtractor implements IRealmExtractor {
|
|
419
|
+
extractRealm(request: Record<string, any>): string | null {
|
|
420
|
+
const host = request.headers?.host;
|
|
421
|
+
if (!host) return null;
|
|
422
|
+
// e.g., "acme.example.com" -> "acme"
|
|
423
|
+
const subdomain = host.split('.')[0];
|
|
424
|
+
return subdomain || null;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
**Async extractor (DB-backed lookup):** `extractRealm` may also return `Promise<string | null>`. `RealmMiddleware` awaits the result with no microtask overhead for sync returns (`instanceof Promise` gate). Async throws and rejected Promises are treated identically to a sync `null` return — the request is rejected with `400 Bad Request` and the internal cause is logged via Nest's `Logger` (never leaked to the client). The same widening applies to `ITenantExtractor.extractTenantId`.
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
@Injectable()
|
|
433
|
+
export class DbRealmExtractor implements IRealmExtractor {
|
|
434
|
+
constructor(private readonly prisma: PrismaService) {}
|
|
435
|
+
|
|
436
|
+
async extractRealm(request: Record<string, any>): Promise<string | null> {
|
|
437
|
+
const host = request.headers?.host;
|
|
438
|
+
if (!host) return null;
|
|
439
|
+
const site = await this.prisma.site.findUnique({ where: { hostname: host } });
|
|
440
|
+
return site ? `site:${site.slug}` : null;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
**Register the module with realm support:**
|
|
446
|
+
|
|
447
|
+
```typescript
|
|
448
|
+
AuthModule.forRootAsync({
|
|
449
|
+
imports: [ConfigModule, DatabaseModule],
|
|
450
|
+
inject: [UsersRepository, RefreshTokenRepository, HostnameRealmExtractor, ConfigService],
|
|
451
|
+
useFactory: (usersRepo, tokenRepo, realmExtractor, config) => ({
|
|
452
|
+
userRepositoryInstance: usersRepo,
|
|
453
|
+
refreshTokenRepositoryInstance: tokenRepo,
|
|
454
|
+
jwtSecret: config.get('JWT_SECRET'),
|
|
455
|
+
realmExtractorInstance: realmExtractor,
|
|
456
|
+
}),
|
|
457
|
+
})
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
`RealmMiddleware` is automatically registered by `AuthModule` — no manual middleware registration needed. When a `realmExtractorInstance` is provided, the middleware calls `extractor.extractRealm(request)` on every request before any guards run. If the extractor returns `null`, the request is rejected with `400 Bad Request` (strict mode).
|
|
461
|
+
|
|
462
|
+
**Use `@CurrentRealm()` in resolvers:**
|
|
463
|
+
|
|
464
|
+
```typescript
|
|
465
|
+
import { CurrentRealm } from '@ambushsoftworks/nestjs-auth-graphql';
|
|
466
|
+
|
|
467
|
+
@Resolver()
|
|
468
|
+
export class AuthResolver extends BaseAuthResolver<User> {
|
|
469
|
+
@Mutation(() => AuthResponse)
|
|
470
|
+
async signup(
|
|
471
|
+
@Args('input') input: SignupInput,
|
|
472
|
+
@CurrentRealm() realm: string,
|
|
473
|
+
@Context() ctx: any,
|
|
474
|
+
) {
|
|
475
|
+
return this.performSignup(input, ctx);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
`BaseAuthResolver` automatically extracts the realm from the GraphQL context via `getRealmFromContext()` and passes it to all service methods. Repository identity-resolution methods (`findByEmail`, `findByPhoneNumber`, `findByOAuthProvider`, `create`) receive the realm as a parameter so your implementation can scope queries accordingly.
|
|
481
|
+
|
|
482
|
+
**JWT realm validation:** The JWT payload includes a `realm` claim. On subsequent requests, `JwtStrategy` validates that the realm in the token matches the realm resolved from the current request. A mismatch results in `401 Unauthorized`.
|
|
483
|
+
|
|
484
|
+
**Rate limiter scoping:** When realms are enabled, rate limiter keys are automatically prefixed with the realm to prevent cross-realm interference (e.g., a lockout in realm A does not affect realm B).
|
|
485
|
+
|
|
486
|
+
**Realms vs. Multi-Tenancy:**
|
|
487
|
+
|
|
488
|
+
| Concern | Realms | Multi-Tenancy |
|
|
489
|
+
|---------|--------|---------------|
|
|
490
|
+
| Partitions | Identity (who the user _is_) | Authorization (what the user _can access_) |
|
|
491
|
+
| Scope | User signup, login, tokens, verification | Permissions, resources, team membership |
|
|
492
|
+
| Same email in multiple? | Yes -- fully independent users | Yes -- same user, different tenant contexts |
|
|
493
|
+
| Guard layer | Middleware (before guards) | Guard (`TenantGuard`, after auth) |
|
|
494
|
+
|
|
495
|
+
Realms and multi-tenancy are orthogonal and can be used together. For example, a white-label SaaS platform might use realms to isolate brand identities and tenancy to manage organizations within each brand.
|
|
496
|
+
|
|
497
|
+
**Note:** Deprecated OAuth controller methods are not realm-aware. Use the current `BaseAuthResolver` OAuth methods for realm-scoped OAuth flows.
|
|
498
|
+
|
|
400
499
|
### API Key Authentication
|
|
401
500
|
|
|
402
501
|
For machine-to-machine auth, provide an `IApiKeyRepository`:
|
|
@@ -520,6 +619,104 @@ The `OAuthController` is automatically registered and handles OAuth callback rou
|
|
|
520
619
|
|
|
521
620
|
When `features.bruteForceProtection` is enabled and a `bruteForceRepositoryInstance` is provided, the module tracks failed login attempts and temporarily locks accounts. The lockout policy (attempt thresholds, lockout duration) is determined by your `IBruteForceRepository` implementation.
|
|
522
621
|
|
|
622
|
+
#### IP Rate Limiting
|
|
623
|
+
|
|
624
|
+
`BruteForceProtectionService.checkIpRateLimit(ipAddress, realm?)` enforces a sliding-window rate limit per IP. Opt in by setting `bruteForce.ipRateLimit`:
|
|
625
|
+
|
|
626
|
+
```typescript
|
|
627
|
+
import { RedisRateLimiter } from './redis-rate-limiter'; // your implementation
|
|
628
|
+
|
|
629
|
+
AuthModule.forRootAsync({
|
|
630
|
+
inject: [RedisRateLimiter],
|
|
631
|
+
useFactory: (redisRateLimiter) => ({
|
|
632
|
+
// ...required options
|
|
633
|
+
rateLimiterInstance: redisRateLimiter, // REQUIRED with ipRateLimit
|
|
634
|
+
bruteForce: {
|
|
635
|
+
ipRateLimit: { maxAttempts: 10, windowMs: 60_000 }, // 10 per minute per IP
|
|
636
|
+
},
|
|
637
|
+
}),
|
|
638
|
+
})
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
When `bruteForce.ipRateLimit` is configured, `AuthModule.forRootAsync` requires an explicit `rateLimiterInstance` and throws `InvalidAuthConfigException` at boot otherwise:
|
|
642
|
+
|
|
643
|
+
```
|
|
644
|
+
[AuthModule] bruteForce.ipRateLimit is configured but rateLimiterInstance is undefined.
|
|
645
|
+
The default InMemoryRateLimiterService is unsafe for multi-replica deployments
|
|
646
|
+
(per-replica counters do not coordinate) and is not auto-applied for IP rate limiting.
|
|
647
|
+
Provide rateLimiterInstance explicitly: a Redis-backed implementation for production,
|
|
648
|
+
or `new InMemoryRateLimiterService()` for single-replica deployments / dev.
|
|
649
|
+
To disable IP rate limiting, remove the bruteForce.ipRateLimit slot.
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
`checkIpRateLimit` reuses the same `IRateLimiter` infrastructure as password-reset throttling — implement once, reuse everywhere. For multi-replica production, back it with Redis (the same pattern documented for the `RefreshTokenService` cache applies). For single-replica or dev, `new InMemoryRateLimiterService()` is acceptable.
|
|
653
|
+
|
|
654
|
+
Threshold is inclusive: with `maxAttempts: 5`, the user is blocked starting on the 5th attempt within the window (record-then-check ordering means `attempts >= maxAttempts` returns `true`). Tune your config accordingly — `maxAttempts: 5` is the first blocked attempt, not the first allowed-over.
|
|
655
|
+
|
|
656
|
+
When realms are enabled, rate-limit keys are namespaced as `auth:ipRate:<realm>:<ipHash>` so a single shared store serves many realms without collisions. IPs are hashed via `hashIp(ip, salt)` (HMAC-SHA256, 16-char hex prefix) before becoming keys; raw IPs are never written to the store or to logs. The salt is resolved once at service construction with the following priority:
|
|
657
|
+
|
|
658
|
+
1. `AUTH_IP_HASH_SALT` env var (recommended — dedicated, rotatable secret)
|
|
659
|
+
2. `options.jwtSecret` (fallback; one-time INFO log when `bruteForce.ipRateLimit` is configured)
|
|
660
|
+
3. Throws `InvalidAuthConfigException` if `bruteForce.ipRateLimit` is configured but neither salt source is available
|
|
661
|
+
|
|
662
|
+
Note: the salt is read from `AuthModuleOptions` (not from `process.env.JWT_SECRET` directly), so consumers wiring their JWT secret via `@nestjs/config` / a secrets manager work correctly without populating `process.env.JWT_SECRET`.
|
|
663
|
+
|
|
664
|
+
When the limit is exceeded, `SecurityEvent.IP_RATE_LIMIT_EXCEEDED` is logged. The method returns `boolean` and never throws — callers branch and produce their own error envelope (typically HTTP 429).
|
|
665
|
+
|
|
666
|
+
#### Brute-Force Cleanup
|
|
667
|
+
|
|
668
|
+
`BruteForceProtectionService.cleanupOldAttempts(olderThan: Date): Promise<number>` deletes failed-attempt records older than the cutoff and returns the deletion count. The package does NOT ship a scheduler — wire one in your application:
|
|
669
|
+
|
|
670
|
+
```typescript
|
|
671
|
+
import { Injectable, Logger } from '@nestjs/common';
|
|
672
|
+
import { Cron } from '@nestjs/schedule';
|
|
673
|
+
import { BruteForceProtectionService } from '@ambushsoftworks/nestjs-auth-graphql';
|
|
674
|
+
|
|
675
|
+
@Injectable()
|
|
676
|
+
export class BruteForceCleanupJob {
|
|
677
|
+
private readonly logger = new Logger(BruteForceCleanupJob.name);
|
|
678
|
+
|
|
679
|
+
constructor(private readonly bruteForce: BruteForceProtectionService) {}
|
|
680
|
+
|
|
681
|
+
@Cron('0 3 * * *') // daily at 03:00
|
|
682
|
+
async cleanup() {
|
|
683
|
+
const ninetyDaysAgo = new Date(Date.now() - 90 * 24 * 60 * 60 * 1000);
|
|
684
|
+
const deleted = await this.bruteForce.cleanupOldAttempts(ninetyDaysAgo);
|
|
685
|
+
this.logger.log(`Cleaned ${deleted} old brute-force-attempt rows`);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
This requires `IBruteForceRepository.deleteOlderThan(beforeDate: Date): Promise<number>` on your repository implementation. Reference Prisma implementation: `return (await this.prisma.bruteForceAttempt.deleteMany({ where: { createdAt: { lt: beforeDate } } })).count;`. Multi-replica deployments should coordinate at the cron layer (advisory lock, leader election) or accept the duplicate-delete cost — `DELETE WHERE createdAt < ?` is idempotent.
|
|
691
|
+
|
|
692
|
+
#### Stay Logged In After Password Change
|
|
693
|
+
|
|
694
|
+
`changePassword` revokes every refresh token for the user (logging out all devices). To keep the current device logged in while logging out the others, compose `changePassword` with `issueAuthSession`:
|
|
695
|
+
|
|
696
|
+
```typescript
|
|
697
|
+
@Mutation(() => ChangePasswordResponse)
|
|
698
|
+
@UseGuards(JwtAuthGuard)
|
|
699
|
+
async changePassword(
|
|
700
|
+
@CurrentUser() user: User,
|
|
701
|
+
@Args('input') input: ChangePasswordInput,
|
|
702
|
+
@Context() ctx: any,
|
|
703
|
+
): Promise<ChangePasswordResponse> {
|
|
704
|
+
const result = await this.performChangePassword(
|
|
705
|
+
user.id,
|
|
706
|
+
input.currentPassword,
|
|
707
|
+
input.newPassword,
|
|
708
|
+
);
|
|
709
|
+
// Mint a fresh session for THIS device. Other devices are already revoked.
|
|
710
|
+
// Use the inherited `getResponseFromContext` helper so cookies work under
|
|
711
|
+
// both Apollo (`ctx.res`) and Express/Fastify (`ctx.req.res`).
|
|
712
|
+
const res = this.getResponseFromContext(ctx);
|
|
713
|
+
const tokens = await this.authService.issueAuthSession(user.id, res);
|
|
714
|
+
return { ...result, accessToken: tokens.accessToken, refreshToken: tokens.refreshToken };
|
|
715
|
+
}
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
`issueAuthSession(userId, res?, realm?)` mints a new access + refresh pair, persists the refresh token, and (when `features.cookieAuth` is enabled and `res` is supplied) sets the auth cookies on the response. The caller is responsible for verifying the user's identity — `issueAuthSession` takes a `userId` and trusts it. Pair it only with flows that have already authenticated the user (`changePassword`, MFA enrollment completion, admin-impersonation reissue, etc.). Emits `SecurityEvent.SESSION_ISSUED`.
|
|
719
|
+
|
|
523
720
|
### Password Policy
|
|
524
721
|
|
|
525
722
|
```typescript
|
|
@@ -609,6 +806,7 @@ jwtPayloadFactoryInstance: {
|
|
|
609
806
|
| `nodeEnv` | `string` | `'production'` | Environment identifier |
|
|
610
807
|
| `passwordPolicy` | `PasswordPolicyConfig` | See [Password Policy](#password-policy) | Password strength rules |
|
|
611
808
|
| `encryptionKey` | `string` | -- | 32-byte hex string for AES-256-GCM (OAuth token encryption) |
|
|
809
|
+
| `bruteForce.ipRateLimit` | `{ maxAttempts, windowMs }` | -- | IP rate-limit policy for `checkIpRateLimit`. When set, `rateLimiterInstance` MUST also be provided explicitly (boot fails with `InvalidAuthConfigException` otherwise). See [IP Rate Limiting](#ip-rate-limiting). |
|
|
612
810
|
|
|
613
811
|
### Feature Flags (`features`)
|
|
614
812
|
|
|
@@ -694,7 +892,8 @@ When `email` is provided, it takes precedence over `emailServiceInstance`.
|
|
|
694
892
|
| `resourcePermissionRepositoryInstance` | `IResourcePermissionRepository` | `null` |
|
|
695
893
|
| `jwtPayloadFactoryInstance` | `IJwtPayloadFactory` | `DefaultJwtPayloadFactory` |
|
|
696
894
|
| `apiKeyRepositoryInstance` | `IApiKeyRepository` | `null` |
|
|
697
|
-
| `rateLimiterInstance` | `IRateLimiter` | `InMemoryRateLimiterService` |
|
|
895
|
+
| `rateLimiterInstance` | `IRateLimiter` | `InMemoryRateLimiterService` (Note: this fallback does NOT apply when `bruteForce.ipRateLimit` is configured — boot fails with `InvalidAuthConfigException` and an explicit `rateLimiterInstance` is required. See [IP Rate Limiting](#ip-rate-limiting) above.) |
|
|
896
|
+
| `realmExtractorInstance` | `IRealmExtractor` | `null` (realms disabled) |
|
|
698
897
|
|
|
699
898
|
---
|
|
700
899
|
|
|
@@ -708,6 +907,7 @@ When `email` is provided, it takes precedence over `emailServiceInstance`.
|
|
|
708
907
|
| `@RequirePermissions('p1', 'p2')` | Method/Class | Require specific permissions |
|
|
709
908
|
| `@CurrentUser()` | Parameter | Inject authenticated user |
|
|
710
909
|
| `@CurrentTenant()` | Parameter | Inject resolved tenant context |
|
|
910
|
+
| `@CurrentRealm()` | Parameter | Inject resolved realm from request context |
|
|
711
911
|
| `@ResourceScope('resourceType', 'argName')` | Method | Resource-level permission scoping |
|
|
712
912
|
|
|
713
913
|
## Guards
|
|
@@ -722,6 +922,8 @@ When `email` is provided, it takes precedence over `emailServiceInstance`.
|
|
|
722
922
|
|
|
723
923
|
### Recommended Guard Chains
|
|
724
924
|
|
|
925
|
+
When realm support is enabled, `RealmMiddleware` runs before all guards (as NestJS middleware) and attaches the resolved realm to `request._realm`. It is registered automatically by `AuthModule` -- see [Realm-Based Identity Isolation](#realm-based-identity-isolation).
|
|
926
|
+
|
|
725
927
|
```typescript
|
|
726
928
|
// JWT only
|
|
727
929
|
{ provide: APP_GUARD, useClass: createAuthGuard(['jwt'], { allowPublic: true }) }
|
|
@@ -769,6 +971,7 @@ export class CustomGuard implements CanActivate {
|
|
|
769
971
|
- **Stateless CSRF protection** for OAuth flows via `OAuthStateService`
|
|
770
972
|
- **`__Host-` cookie prefix** support for enhanced cookie security
|
|
771
973
|
- **Separate HMAC secrets** for refresh tokens, verification codes, and OAuth state
|
|
974
|
+
- **Realm-based identity isolation** with JWT realm claim validation and realm-scoped rate limiting
|
|
772
975
|
|
|
773
976
|
## License
|
|
774
977
|
|
package/dist/auth.module.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DynamicModule } from '@nestjs/common';
|
|
1
|
+
import { DynamicModule, MiddlewareConsumer, NestModule } from '@nestjs/common';
|
|
2
2
|
import { ModuleMetadata } from '@nestjs/common/interfaces';
|
|
3
3
|
import { IUserRepository } from './interfaces/user-repository.interface';
|
|
4
4
|
import { IEmailService } from './interfaces/email-service.interface';
|
|
@@ -11,6 +11,7 @@ import { IBiometricRepository } from './interfaces/biometric-repository.interfac
|
|
|
11
11
|
import { IAuthLogger } from './interfaces/auth-logger.interface';
|
|
12
12
|
import { ITenantRepository } from './interfaces/tenant-repository.interface';
|
|
13
13
|
import { ITenantExtractor } from './interfaces/tenant-extractor.interface';
|
|
14
|
+
import { IRealmExtractor } from './interfaces/realm-extractor.interface';
|
|
14
15
|
import { IResourcePermissionRepository } from './interfaces/resource-permission-repository.interface';
|
|
15
16
|
import { IJwtPayloadFactory } from './interfaces/jwt-payload-factory.interface';
|
|
16
17
|
import { IApiKeyRepository } from './interfaces/api-key-repository.interface';
|
|
@@ -46,6 +47,7 @@ export interface AuthModuleOptions {
|
|
|
46
47
|
nodeEnv?: string;
|
|
47
48
|
tenantRepositoryInstance?: ITenantRepository;
|
|
48
49
|
tenantExtractorInstance?: ITenantExtractor;
|
|
50
|
+
realmExtractorInstance?: IRealmExtractor;
|
|
49
51
|
resourcePermissionRepositoryInstance?: IResourcePermissionRepository;
|
|
50
52
|
jwtPayloadFactoryInstance?: IJwtPayloadFactory;
|
|
51
53
|
apiKeyRepositoryInstance?: IApiKeyRepository;
|
|
@@ -98,6 +100,12 @@ export interface AuthModuleOptions {
|
|
|
98
100
|
encryptionKey?: string;
|
|
99
101
|
passwordPolicy?: PasswordPolicyConfig;
|
|
100
102
|
rateLimiterInstance?: IRateLimiter;
|
|
103
|
+
bruteForce?: {
|
|
104
|
+
ipRateLimit?: {
|
|
105
|
+
maxAttempts: number;
|
|
106
|
+
windowMs: number;
|
|
107
|
+
};
|
|
108
|
+
};
|
|
101
109
|
email?: {
|
|
102
110
|
sender: IEmailSender;
|
|
103
111
|
from: {
|
|
@@ -117,8 +125,10 @@ export interface AuthModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'>
|
|
|
117
125
|
useFactory: (...args: any[]) => Promise<AuthModuleOptions> | AuthModuleOptions;
|
|
118
126
|
inject?: any[];
|
|
119
127
|
}
|
|
128
|
+
export declare function validateAuthModuleOptions(opts: AuthModuleOptions): void;
|
|
120
129
|
export { AUTH_MODULE_OPTIONS, USER_REPOSITORY, REFRESH_TOKEN_REPOSITORY, EMAIL_SERVICE, SMS_SERVICE, AUTH_LIFECYCLE_HOOKS, VERIFICATION_REPOSITORY, BRUTE_FORCE_REPOSITORY, BIOMETRIC_REPOSITORY, AUTH_LOGGER, RATE_LIMITER, TENANT_REPOSITORY, TENANT_EXTRACTOR, RESOURCE_PERMISSION_REPOSITORY, JWT_PAYLOAD_FACTORY, API_KEY_REPOSITORY, } from './constants';
|
|
121
|
-
export declare class AuthModule {
|
|
130
|
+
export declare class AuthModule implements NestModule {
|
|
131
|
+
configure(consumer: MiddlewareConsumer): void;
|
|
122
132
|
static forRootAsync(options: AuthModuleAsyncOptions): DynamicModule;
|
|
123
133
|
}
|
|
124
134
|
//# sourceMappingURL=auth.module.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.module.d.ts","sourceRoot":"","sources":["../src/auth.module.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"auth.module.d.ts","sourceRoot":"","sources":["../src/auth.module.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.module.js
CHANGED
|
@@ -8,7 +8,9 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
8
8
|
var AuthModule_1;
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.AuthModule = exports.API_KEY_REPOSITORY = exports.JWT_PAYLOAD_FACTORY = exports.RESOURCE_PERMISSION_REPOSITORY = exports.TENANT_EXTRACTOR = exports.TENANT_REPOSITORY = exports.RATE_LIMITER = exports.AUTH_LOGGER = exports.BIOMETRIC_REPOSITORY = exports.BRUTE_FORCE_REPOSITORY = exports.VERIFICATION_REPOSITORY = exports.AUTH_LIFECYCLE_HOOKS = exports.SMS_SERVICE = exports.EMAIL_SERVICE = exports.REFRESH_TOKEN_REPOSITORY = exports.USER_REPOSITORY = exports.AUTH_MODULE_OPTIONS = void 0;
|
|
11
|
+
exports.validateAuthModuleOptions = validateAuthModuleOptions;
|
|
11
12
|
const common_1 = require("@nestjs/common");
|
|
13
|
+
const realm_middleware_1 = require("./middleware/realm.middleware");
|
|
12
14
|
const jwt_1 = require("@nestjs/jwt");
|
|
13
15
|
const passport_1 = require("@nestjs/passport");
|
|
14
16
|
const auth_service_1 = require("./services/auth.service");
|
|
@@ -38,8 +40,31 @@ const api_key_strategy_1 = require("./strategies/api-key.strategy");
|
|
|
38
40
|
const default_jwt_payload_factory_1 = require("./services/default-jwt-payload-factory");
|
|
39
41
|
const constants_1 = require("./constants");
|
|
40
42
|
const in_memory_rate_limiter_service_1 = require("./services/in-memory-rate-limiter.service");
|
|
43
|
+
const invalid_auth_config_exception_1 = require("./exceptions/invalid-auth-config.exception");
|
|
41
44
|
const configurable_email_service_1 = require("./services/configurable-email.service");
|
|
42
45
|
const default_email_template_renderer_1 = require("./services/default-email-template-renderer");
|
|
46
|
+
function validateAuthModuleOptions(opts) {
|
|
47
|
+
const ipRateLimit = opts.bruteForce?.ipRateLimit;
|
|
48
|
+
if (ipRateLimit && !opts.rateLimiterInstance) {
|
|
49
|
+
throw new invalid_auth_config_exception_1.InvalidAuthConfigException('[AuthModule] bruteForce.ipRateLimit is configured but rateLimiterInstance ' +
|
|
50
|
+
'is undefined. The default InMemoryRateLimiterService is unsafe for ' +
|
|
51
|
+
'multi-replica deployments (per-replica counters do not coordinate) ' +
|
|
52
|
+
'and is not auto-applied for IP rate limiting. Provide rateLimiterInstance ' +
|
|
53
|
+
'explicitly: a Redis-backed implementation for production, or ' +
|
|
54
|
+
'`new InMemoryRateLimiterService()` for single-replica deployments / dev. ' +
|
|
55
|
+
'To disable IP rate limiting, remove the bruteForce.ipRateLimit slot.');
|
|
56
|
+
}
|
|
57
|
+
if (ipRateLimit) {
|
|
58
|
+
const { maxAttempts, windowMs } = ipRateLimit;
|
|
59
|
+
if (!Number.isInteger(maxAttempts) || maxAttempts <= 0) {
|
|
60
|
+
throw new invalid_auth_config_exception_1.InvalidAuthConfigException(`[AuthModule] bruteForce.ipRateLimit.maxAttempts must be a positive integer; received ${String(maxAttempts)}. Zero would block every request; negative / fractional values are ` +
|
|
61
|
+
'invalid. Use a positive integer such as 10 (10 attempts per window).');
|
|
62
|
+
}
|
|
63
|
+
if (!Number.isInteger(windowMs) || windowMs <= 0) {
|
|
64
|
+
throw new invalid_auth_config_exception_1.InvalidAuthConfigException(`[AuthModule] bruteForce.ipRateLimit.windowMs must be a positive integer; received ${String(windowMs)}. Use a positive integer in milliseconds such as 60000 (1-minute window).`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
43
68
|
var constants_2 = require("./constants");
|
|
44
69
|
Object.defineProperty(exports, "AUTH_MODULE_OPTIONS", { enumerable: true, get: function () { return constants_2.AUTH_MODULE_OPTIONS; } });
|
|
45
70
|
Object.defineProperty(exports, "USER_REPOSITORY", { enumerable: true, get: function () { return constants_2.USER_REPOSITORY; } });
|
|
@@ -58,11 +83,15 @@ Object.defineProperty(exports, "RESOURCE_PERMISSION_REPOSITORY", { enumerable: t
|
|
|
58
83
|
Object.defineProperty(exports, "JWT_PAYLOAD_FACTORY", { enumerable: true, get: function () { return constants_2.JWT_PAYLOAD_FACTORY; } });
|
|
59
84
|
Object.defineProperty(exports, "API_KEY_REPOSITORY", { enumerable: true, get: function () { return constants_2.API_KEY_REPOSITORY; } });
|
|
60
85
|
let AuthModule = AuthModule_1 = class AuthModule {
|
|
86
|
+
configure(consumer) {
|
|
87
|
+
consumer.apply(realm_middleware_1.RealmMiddleware).forRoutes('*');
|
|
88
|
+
}
|
|
61
89
|
static forRootAsync(options) {
|
|
62
90
|
const optionsProvider = {
|
|
63
91
|
provide: constants_1.AUTH_MODULE_OPTIONS,
|
|
64
92
|
useFactory: async (...args) => {
|
|
65
93
|
const opts = await options.useFactory(...args);
|
|
94
|
+
validateAuthModuleOptions(opts);
|
|
66
95
|
if (opts.cookie?.useHostPrefix) {
|
|
67
96
|
if (opts.cookie.secure === false) {
|
|
68
97
|
throw new Error('[AuthModule] cookie.useHostPrefix requires cookie.secure to be true (or unset). ' +
|
|
@@ -209,6 +238,13 @@ let AuthModule = AuthModule_1 = class AuthModule {
|
|
|
209
238
|
return opts.tenantExtractorInstance || null;
|
|
210
239
|
},
|
|
211
240
|
},
|
|
241
|
+
{
|
|
242
|
+
provide: constants_1.REALM_EXTRACTOR,
|
|
243
|
+
inject: [constants_1.AUTH_MODULE_OPTIONS],
|
|
244
|
+
useFactory: (opts) => {
|
|
245
|
+
return opts.realmExtractorInstance || null;
|
|
246
|
+
},
|
|
247
|
+
},
|
|
212
248
|
{
|
|
213
249
|
provide: constants_1.RESOURCE_PERMISSION_REPOSITORY,
|
|
214
250
|
inject: [constants_1.AUTH_MODULE_OPTIONS],
|
|
@@ -297,6 +333,7 @@ let AuthModule = AuthModule_1 = class AuthModule {
|
|
|
297
333
|
return new api_key_strategy_1.ApiKeyStrategy(options.apiKeyRepositoryInstance);
|
|
298
334
|
},
|
|
299
335
|
},
|
|
336
|
+
realm_middleware_1.RealmMiddleware,
|
|
300
337
|
tenant_guard_1.TenantGuard,
|
|
301
338
|
permission_guard_1.PermissionGuard,
|
|
302
339
|
],
|
|
@@ -316,6 +353,7 @@ let AuthModule = AuthModule_1 = class AuthModule {
|
|
|
316
353
|
constants_1.REFRESH_TOKEN_REPOSITORY,
|
|
317
354
|
constants_1.TENANT_REPOSITORY,
|
|
318
355
|
constants_1.TENANT_EXTRACTOR,
|
|
356
|
+
constants_1.REALM_EXTRACTOR,
|
|
319
357
|
constants_1.RESOURCE_PERMISSION_REPOSITORY,
|
|
320
358
|
constants_1.JWT_PAYLOAD_FACTORY,
|
|
321
359
|
constants_1.API_KEY_REPOSITORY,
|
package/dist/auth.module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../src/auth.module.ts"],"names":[],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../src/auth.module.ts"],"names":[],"mappings":"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"}
|
package/dist/constants.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export declare const RESOURCE_PERMISSION_REPOSITORY = "RESOURCE_PERMISSION_REPOS
|
|
|
15
15
|
export declare const JWT_PAYLOAD_FACTORY = "JWT_PAYLOAD_FACTORY";
|
|
16
16
|
export declare const API_KEY_REPOSITORY = "API_KEY_REPOSITORY";
|
|
17
17
|
export declare const TENANT_HEADER_NAME = "TENANT_HEADER_NAME";
|
|
18
|
+
export declare const REALM_EXTRACTOR = "REALM_EXTRACTOR";
|
|
18
19
|
export declare const PERMISSIONS_KEY = "permissions";
|
|
19
20
|
export declare const SKIP_TENANT_KEY = "skipTenant";
|
|
20
21
|
export declare const PUBLIC_ENDPOINT_KEY = "isPublicEndpoint";
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AAMzD,eAAO,MAAM,eAAe,oBAAoB,CAAC;AAMjD,eAAO,MAAM,wBAAwB,6BAA6B,CAAC;AAMnE,eAAO,MAAM,aAAa,kBAAkB,CAAC;AAM7C,eAAO,MAAM,WAAW,gBAAgB,CAAC;AAMzC,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAM3D,eAAO,MAAM,uBAAuB,4BAA4B,CAAC;AAMjE,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAM/D,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAO3D,eAAO,MAAM,WAAW,gBAAgB,CAAC;AAOzC,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAU3C,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AAMrD,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AAMnD,eAAO,MAAM,8BAA8B,mCAAmC,CAAC;AAM/E,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AAMzD,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AAMvD,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AAMzD,eAAO,MAAM,eAAe,oBAAoB,CAAC;AAMjD,eAAO,MAAM,wBAAwB,6BAA6B,CAAC;AAMnE,eAAO,MAAM,aAAa,kBAAkB,CAAC;AAM7C,eAAO,MAAM,WAAW,gBAAgB,CAAC;AAMzC,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAM3D,eAAO,MAAM,uBAAuB,4BAA4B,CAAC;AAMjE,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAM/D,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAO3D,eAAO,MAAM,WAAW,gBAAgB,CAAC;AAOzC,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAU3C,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AAMrD,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AAMnD,eAAO,MAAM,8BAA8B,mCAAmC,CAAC;AAM/E,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AAMzD,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AAMvD,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AAWvD,eAAO,MAAM,eAAe,oBAAoB,CAAC;AAOjD,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAG7C,eAAO,MAAM,eAAe,eAAe,CAAC;AAG5C,eAAO,MAAM,mBAAmB,qBAAqB,CAAC;AAGtD,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAUlD,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAM7D,eAAO,MAAM,yBAAyB,8BAA8B,CAAC;AAMrE,eAAO,MAAM,qBAAqB,0BAA0B,CAAC"}
|
package/dist/constants.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.USER_REPOSITORY_PHONE = exports.USER_REPOSITORY_BIOMETRIC = exports.USER_REPOSITORY_OAUTH = exports.RESOURCE_SCOPE_KEY = exports.PUBLIC_ENDPOINT_KEY = exports.SKIP_TENANT_KEY = exports.PERMISSIONS_KEY = exports.TENANT_HEADER_NAME = exports.API_KEY_REPOSITORY = exports.JWT_PAYLOAD_FACTORY = exports.RESOURCE_PERMISSION_REPOSITORY = exports.TENANT_EXTRACTOR = exports.TENANT_REPOSITORY = exports.RATE_LIMITER = exports.AUTH_LOGGER = exports.BIOMETRIC_REPOSITORY = exports.BRUTE_FORCE_REPOSITORY = exports.VERIFICATION_REPOSITORY = exports.AUTH_LIFECYCLE_HOOKS = exports.SMS_SERVICE = exports.EMAIL_SERVICE = exports.REFRESH_TOKEN_REPOSITORY = exports.USER_REPOSITORY = exports.AUTH_MODULE_OPTIONS = void 0;
|
|
3
|
+
exports.USER_REPOSITORY_PHONE = exports.USER_REPOSITORY_BIOMETRIC = exports.USER_REPOSITORY_OAUTH = exports.RESOURCE_SCOPE_KEY = exports.PUBLIC_ENDPOINT_KEY = exports.SKIP_TENANT_KEY = exports.PERMISSIONS_KEY = exports.REALM_EXTRACTOR = exports.TENANT_HEADER_NAME = exports.API_KEY_REPOSITORY = exports.JWT_PAYLOAD_FACTORY = exports.RESOURCE_PERMISSION_REPOSITORY = exports.TENANT_EXTRACTOR = exports.TENANT_REPOSITORY = exports.RATE_LIMITER = exports.AUTH_LOGGER = exports.BIOMETRIC_REPOSITORY = exports.BRUTE_FORCE_REPOSITORY = exports.VERIFICATION_REPOSITORY = exports.AUTH_LIFECYCLE_HOOKS = exports.SMS_SERVICE = exports.EMAIL_SERVICE = exports.REFRESH_TOKEN_REPOSITORY = exports.USER_REPOSITORY = exports.AUTH_MODULE_OPTIONS = void 0;
|
|
4
4
|
exports.AUTH_MODULE_OPTIONS = 'AUTH_MODULE_OPTIONS';
|
|
5
5
|
exports.USER_REPOSITORY = 'USER_REPOSITORY';
|
|
6
6
|
exports.REFRESH_TOKEN_REPOSITORY = 'REFRESH_TOKEN_REPOSITORY';
|
|
@@ -18,6 +18,7 @@ exports.RESOURCE_PERMISSION_REPOSITORY = 'RESOURCE_PERMISSION_REPOSITORY';
|
|
|
18
18
|
exports.JWT_PAYLOAD_FACTORY = 'JWT_PAYLOAD_FACTORY';
|
|
19
19
|
exports.API_KEY_REPOSITORY = 'API_KEY_REPOSITORY';
|
|
20
20
|
exports.TENANT_HEADER_NAME = 'TENANT_HEADER_NAME';
|
|
21
|
+
exports.REALM_EXTRACTOR = 'REALM_EXTRACTOR';
|
|
21
22
|
exports.PERMISSIONS_KEY = 'permissions';
|
|
22
23
|
exports.SKIP_TENANT_KEY = 'skipTenant';
|
|
23
24
|
exports.PUBLIC_ENDPOINT_KEY = 'isPublicEndpoint';
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAgBa,QAAA,mBAAmB,GAAG,qBAAqB,CAAC;AAM5C,QAAA,eAAe,GAAG,iBAAiB,CAAC;AAMpC,QAAA,wBAAwB,GAAG,0BAA0B,CAAC;AAMtD,QAAA,aAAa,GAAG,eAAe,CAAC;AAMhC,QAAA,WAAW,GAAG,aAAa,CAAC;AAM5B,QAAA,oBAAoB,GAAG,sBAAsB,CAAC;AAM9C,QAAA,uBAAuB,GAAG,yBAAyB,CAAC;AAMpD,QAAA,sBAAsB,GAAG,wBAAwB,CAAC;AAMlD,QAAA,oBAAoB,GAAG,sBAAsB,CAAC;AAO9C,QAAA,WAAW,GAAG,aAAa,CAAC;AAO5B,QAAA,YAAY,GAAG,cAAc,CAAC;AAU9B,QAAA,iBAAiB,GAAG,mBAAmB,CAAC;AAMxC,QAAA,gBAAgB,GAAG,kBAAkB,CAAC;AAMtC,QAAA,8BAA8B,GAAG,gCAAgC,CAAC;AAMlE,QAAA,mBAAmB,GAAG,qBAAqB,CAAC;AAM5C,QAAA,kBAAkB,GAAG,oBAAoB,CAAC;AAM1C,QAAA,kBAAkB,GAAG,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAgBa,QAAA,mBAAmB,GAAG,qBAAqB,CAAC;AAM5C,QAAA,eAAe,GAAG,iBAAiB,CAAC;AAMpC,QAAA,wBAAwB,GAAG,0BAA0B,CAAC;AAMtD,QAAA,aAAa,GAAG,eAAe,CAAC;AAMhC,QAAA,WAAW,GAAG,aAAa,CAAC;AAM5B,QAAA,oBAAoB,GAAG,sBAAsB,CAAC;AAM9C,QAAA,uBAAuB,GAAG,yBAAyB,CAAC;AAMpD,QAAA,sBAAsB,GAAG,wBAAwB,CAAC;AAMlD,QAAA,oBAAoB,GAAG,sBAAsB,CAAC;AAO9C,QAAA,WAAW,GAAG,aAAa,CAAC;AAO5B,QAAA,YAAY,GAAG,cAAc,CAAC;AAU9B,QAAA,iBAAiB,GAAG,mBAAmB,CAAC;AAMxC,QAAA,gBAAgB,GAAG,kBAAkB,CAAC;AAMtC,QAAA,8BAA8B,GAAG,gCAAgC,CAAC;AAMlE,QAAA,mBAAmB,GAAG,qBAAqB,CAAC;AAM5C,QAAA,kBAAkB,GAAG,oBAAoB,CAAC;AAM1C,QAAA,kBAAkB,GAAG,oBAAoB,CAAC;AAW1C,QAAA,eAAe,GAAG,iBAAiB,CAAC;AAOpC,QAAA,eAAe,GAAG,aAAa,CAAC;AAGhC,QAAA,eAAe,GAAG,YAAY,CAAC;AAG/B,QAAA,mBAAmB,GAAG,kBAAkB,CAAC;AAGzC,QAAA,kBAAkB,GAAG,eAAe,CAAC;AAUrC,QAAA,qBAAqB,GAAG,uBAAuB,CAAC;AAMhD,QAAA,yBAAyB,GAAG,2BAA2B,CAAC;AAMxD,QAAA,qBAAqB,GAAG,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"current-realm.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/current-realm.decorator.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,YAAY,mDAKxB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CurrentRealm = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
const graphql_1 = require("@nestjs/graphql");
|
|
6
|
+
exports.CurrentRealm = (0, common_1.createParamDecorator)((_data, context) => {
|
|
7
|
+
const ctx = graphql_1.GqlExecutionContext.create(context);
|
|
8
|
+
return ctx.getContext().req._realm;
|
|
9
|
+
});
|
|
10
|
+
//# sourceMappingURL=current-realm.decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"current-realm.decorator.js","sourceRoot":"","sources":["../../src/decorators/current-realm.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAAwE;AACxE,6CAAsD;AAiBzC,QAAA,YAAY,GAAG,IAAA,6BAAoB,EAC9C,CAAC,KAAc,EAAE,OAAyB,EAAsB,EAAE;IAChE,MAAM,GAAG,GAAG,6BAAmB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAChD,OAAO,GAAG,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC;AACrC,CAAC,CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt-payload.interface.d.ts","sourceRoot":"","sources":["../../src/dto/jwt-payload.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"jwt-payload.interface.d.ts","sourceRoot":"","sources":["../../src/dto/jwt-payload.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invalid-auth-config.exception.d.ts","sourceRoot":"","sources":["../../src/exceptions/invalid-auth-config.exception.ts"],"names":[],"mappings":"AAkBA,qBAAa,0BAA2B,SAAQ,KAAK;gBAKvC,OAAO,EAAE,MAAM;CAO5B"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InvalidAuthConfigException = void 0;
|
|
4
|
+
class InvalidAuthConfigException extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'InvalidAuthConfigException';
|
|
8
|
+
Object.setPrototypeOf(this, InvalidAuthConfigException.prototype);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.InvalidAuthConfigException = InvalidAuthConfigException;
|
|
12
|
+
//# sourceMappingURL=invalid-auth-config.exception.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invalid-auth-config.exception.js","sourceRoot":"","sources":["../../src/exceptions/invalid-auth-config.exception.ts"],"names":[],"mappings":";;;AAkBA,MAAa,0BAA2B,SAAQ,KAAK;IAKnD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;QAGzC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,0BAA0B,CAAC,SAAS,CAAC,CAAC;IACpE,CAAC;CACF;AAZD,gEAYC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant.guard.d.ts","sourceRoot":"","sources":["../../src/guards/tenant.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EACX,gBAAgB,EAQjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,2CAA2C,CAAC;AAc9E,qBACa,WAAY,YAAW,WAAW;IAI3C,OAAO,CAAC,QAAQ,CAAC,SAAS;IACY,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;IAChC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAL3E,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;gBAGpC,SAAS,EAAE,SAAS,EACkB,eAAe,CAAC,EAAE,gBAAgB,YAAA,EACjC,gBAAgB,CAAC,EAAE,iBAAiB,YAAA;IAGxF,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"tenant.guard.d.ts","sourceRoot":"","sources":["../../src/guards/tenant.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EACX,gBAAgB,EAQjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,2CAA2C,CAAC;AAc9E,qBACa,WAAY,YAAW,WAAW;IAI3C,OAAO,CAAC,QAAQ,CAAC,SAAS;IACY,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;IAChC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAL3E,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;gBAGpC,SAAS,EAAE,SAAS,EACkB,eAAe,CAAC,EAAE,gBAAgB,YAAA,EACjC,gBAAgB,CAAC,EAAE,iBAAiB,YAAA;IAGxF,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;CAmF/D"}
|
|
@@ -45,7 +45,15 @@ let TenantGuard = TenantGuard_1 = class TenantGuard {
|
|
|
45
45
|
if (!this.tenantExtractor) {
|
|
46
46
|
throw new common_1.BadRequestException('Tenant ID required');
|
|
47
47
|
}
|
|
48
|
-
|
|
48
|
+
let tenantId;
|
|
49
|
+
try {
|
|
50
|
+
const result = this.tenantExtractor.extractTenantId(request);
|
|
51
|
+
tenantId = result instanceof Promise ? await result : result;
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
this.logger.error(`Tenant extractor failed: ${err instanceof Error ? err.message : String(err)}`, err instanceof Error ? err.stack : undefined);
|
|
55
|
+
throw new common_1.BadRequestException('Tenant ID required');
|
|
56
|
+
}
|
|
49
57
|
if (!tenantId) {
|
|
50
58
|
throw new common_1.BadRequestException('Tenant ID required');
|
|
51
59
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant.guard.js","sourceRoot":"","sources":["../../src/guards/tenant.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAWwB;AACxB,uCAAyC;AACzC,qEAA+D;AAC/D,4CAAoF;AACpF,kEAAmE;AAiB5D,IAAM,WAAW,mBAAjB,MAAM,WAAW;IAGtB,YACmB,SAAoB,EACC,eAAmD,EAClD,gBAAqD;QAF3E,cAAS,GAAT,SAAS,CAAW;QACkB,oBAAe,GAAf,eAAe,CAAmB;QACjC,qBAAgB,GAAhB,gBAAgB,CAAoB;QAL7E,WAAM,GAAG,IAAI,eAAM,CAAC,aAAW,CAAC,IAAI,CAAC,CAAC;IAMpD,CAAC;IAEJ,KAAK,CAAC,WAAW,CAAC,OAAyB;QAEzC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAU,gCAAa,EAAE;YACxE,OAAO,CAAC,UAAU,EAAE;YACpB,OAAO,CAAC,QAAQ,EAAE;SACnB,CAAC,CAAC;QACH,IAAI,QAAQ;YAAE,OAAO,IAAI,CAAC;QAG1B,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAU,2BAAe,EAAE;YAC5E,OAAO,CAAC,UAAU,EAAE;YACpB,OAAO,CAAC,QAAQ,EAAE;SACnB,CAAC,CAAC;QACH,IAAI,UAAU;YAAE,OAAO,IAAI,CAAC;QAG5B,IAAI,CAAC,IAAI,CAAC,gBAAgB;YAAE,OAAO,IAAI,CAAC;QAExC,MAAM,OAAO,GAAG,IAAA,yCAAqB,EAAC,OAAO,CAAC,CAAC;QAG/C,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1B,MAAM,IAAI,4BAAmB,CAAC,oBAAoB,CAAC,CAAC;QACtD,CAAC;
|
|
1
|
+
{"version":3,"file":"tenant.guard.js","sourceRoot":"","sources":["../../src/guards/tenant.guard.ts"],"names":[],"mappings":"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"}
|