@lenne.tech/nest-server 11.7.0 → 11.7.2

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.
Files changed (120) hide show
  1. package/dist/config.env.js +17 -1
  2. package/dist/config.env.js.map +1 -1
  3. package/dist/core/common/interfaces/server-options.interface.d.ts +35 -15
  4. package/dist/core/modules/auth/core-auth.controller.d.ts +1 -0
  5. package/dist/core/modules/auth/core-auth.controller.js +29 -3
  6. package/dist/core/modules/auth/core-auth.controller.js.map +1 -1
  7. package/dist/core/modules/auth/core-auth.module.js +14 -1
  8. package/dist/core/modules/auth/core-auth.module.js.map +1 -1
  9. package/dist/core/modules/auth/core-auth.resolver.d.ts +1 -0
  10. package/dist/core/modules/auth/core-auth.resolver.js +21 -3
  11. package/dist/core/modules/auth/core-auth.resolver.js.map +1 -1
  12. package/dist/core/modules/auth/exceptions/legacy-auth-disabled.exception.d.ts +4 -0
  13. package/dist/core/modules/auth/exceptions/legacy-auth-disabled.exception.js +17 -0
  14. package/dist/core/modules/auth/exceptions/legacy-auth-disabled.exception.js.map +1 -0
  15. package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.d.ts +9 -0
  16. package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.js +74 -0
  17. package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.js.map +1 -0
  18. package/dist/core/modules/auth/interfaces/auth-provider.interface.d.ts +7 -0
  19. package/dist/core/modules/auth/interfaces/auth-provider.interface.js +5 -0
  20. package/dist/core/modules/auth/interfaces/auth-provider.interface.js.map +1 -0
  21. package/dist/core/modules/auth/interfaces/core-auth-user.interface.d.ts +1 -0
  22. package/dist/core/modules/auth/services/core-auth.service.d.ts +10 -1
  23. package/dist/core/modules/auth/services/core-auth.service.js +141 -9
  24. package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
  25. package/dist/core/modules/auth/services/legacy-auth-rate-limiter.service.d.ts +31 -0
  26. package/dist/core/modules/auth/services/legacy-auth-rate-limiter.service.js +153 -0
  27. package/dist/core/modules/auth/services/legacy-auth-rate-limiter.service.js.map +1 -0
  28. package/dist/core/modules/better-auth/better-auth-migration-status.model.d.ts +10 -0
  29. package/dist/core/modules/better-auth/better-auth-migration-status.model.js +57 -0
  30. package/dist/core/modules/better-auth/better-auth-migration-status.model.js.map +1 -0
  31. package/dist/core/modules/better-auth/better-auth-rate-limiter.service.js +1 -1
  32. package/dist/core/modules/better-auth/better-auth-rate-limiter.service.js.map +1 -1
  33. package/dist/core/modules/better-auth/better-auth-user.mapper.d.ts +33 -0
  34. package/dist/core/modules/better-auth/better-auth-user.mapper.js +395 -0
  35. package/dist/core/modules/better-auth/better-auth-user.mapper.js.map +1 -1
  36. package/dist/core/modules/better-auth/better-auth.config.js +29 -10
  37. package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
  38. package/dist/core/modules/better-auth/better-auth.middleware.d.ts +1 -0
  39. package/dist/core/modules/better-auth/better-auth.middleware.js +55 -1
  40. package/dist/core/modules/better-auth/better-auth.middleware.js.map +1 -1
  41. package/dist/core/modules/better-auth/better-auth.module.d.ts +1 -1
  42. package/dist/core/modules/better-auth/better-auth.module.js +46 -18
  43. package/dist/core/modules/better-auth/better-auth.module.js.map +1 -1
  44. package/dist/core/modules/better-auth/better-auth.resolver.js +0 -11
  45. package/dist/core/modules/better-auth/better-auth.resolver.js.map +1 -1
  46. package/dist/core/modules/better-auth/better-auth.service.d.ts +22 -1
  47. package/dist/core/modules/better-auth/better-auth.service.js +209 -8
  48. package/dist/core/modules/better-auth/better-auth.service.js.map +1 -1
  49. package/dist/core/modules/better-auth/better-auth.types.d.ts +2 -0
  50. package/dist/core/modules/better-auth/better-auth.types.js.map +1 -1
  51. package/dist/core/modules/better-auth/core-better-auth.controller.d.ts +1 -0
  52. package/dist/core/modules/better-auth/core-better-auth.controller.js +15 -2
  53. package/dist/core/modules/better-auth/core-better-auth.controller.js.map +1 -1
  54. package/dist/core/modules/better-auth/core-better-auth.resolver.d.ts +7 -0
  55. package/dist/core/modules/better-auth/core-better-auth.resolver.js +72 -12
  56. package/dist/core/modules/better-auth/core-better-auth.resolver.js.map +1 -1
  57. package/dist/core/modules/better-auth/index.d.ts +1 -0
  58. package/dist/core/modules/better-auth/index.js +1 -0
  59. package/dist/core/modules/better-auth/index.js.map +1 -1
  60. package/dist/core/modules/user/core-user.service.d.ts +7 -1
  61. package/dist/core/modules/user/core-user.service.js +57 -3
  62. package/dist/core/modules/user/core-user.service.js.map +1 -1
  63. package/dist/core/modules/user/interfaces/core-user-service-options.interface.d.ts +4 -0
  64. package/dist/core/modules/user/interfaces/core-user-service-options.interface.js +3 -0
  65. package/dist/core/modules/user/interfaces/core-user-service-options.interface.js.map +1 -0
  66. package/dist/core.module.d.ts +3 -0
  67. package/dist/core.module.js +136 -55
  68. package/dist/core.module.js.map +1 -1
  69. package/dist/index.d.ts +5 -0
  70. package/dist/index.js +5 -0
  71. package/dist/index.js.map +1 -1
  72. package/dist/server/modules/auth/auth.resolver.js +2 -0
  73. package/dist/server/modules/auth/auth.resolver.js.map +1 -1
  74. package/dist/server/modules/better-auth/better-auth.module.d.ts +1 -1
  75. package/dist/server/modules/better-auth/better-auth.module.js +2 -1
  76. package/dist/server/modules/better-auth/better-auth.module.js.map +1 -1
  77. package/dist/server/modules/better-auth/better-auth.resolver.d.ts +5 -0
  78. package/dist/server/modules/better-auth/better-auth.resolver.js +27 -11
  79. package/dist/server/modules/better-auth/better-auth.resolver.js.map +1 -1
  80. package/dist/server/modules/user/user.controller.js +0 -8
  81. package/dist/server/modules/user/user.controller.js.map +1 -1
  82. package/dist/server/modules/user/user.service.d.ts +3 -1
  83. package/dist/server/modules/user/user.service.js +7 -3
  84. package/dist/server/modules/user/user.service.js.map +1 -1
  85. package/dist/tsconfig.build.tsbuildinfo +1 -1
  86. package/package.json +1 -1
  87. package/src/config.env.ts +32 -2
  88. package/src/core/common/interfaces/server-options.interface.ts +304 -58
  89. package/src/core/modules/auth/core-auth.controller.ts +94 -6
  90. package/src/core/modules/auth/core-auth.module.ts +15 -1
  91. package/src/core/modules/auth/core-auth.resolver.ts +71 -3
  92. package/src/core/modules/auth/exceptions/legacy-auth-disabled.exception.ts +35 -0
  93. package/src/core/modules/auth/guards/legacy-auth-rate-limit.guard.ts +109 -0
  94. package/src/core/modules/auth/interfaces/auth-provider.interface.ts +86 -0
  95. package/src/core/modules/auth/interfaces/core-auth-user.interface.ts +6 -0
  96. package/src/core/modules/auth/services/core-auth.service.ts +245 -6
  97. package/src/core/modules/auth/services/legacy-auth-rate-limiter.service.ts +283 -0
  98. package/src/core/modules/better-auth/INTEGRATION-CHECKLIST.md +255 -0
  99. package/src/core/modules/better-auth/README.md +565 -208
  100. package/src/core/modules/better-auth/better-auth-migration-status.model.ts +73 -0
  101. package/src/core/modules/better-auth/better-auth-rate-limiter.service.ts +1 -1
  102. package/src/core/modules/better-auth/better-auth-user.mapper.ts +737 -0
  103. package/src/core/modules/better-auth/better-auth.config.ts +45 -15
  104. package/src/core/modules/better-auth/better-auth.middleware.ts +85 -2
  105. package/src/core/modules/better-auth/better-auth.module.ts +83 -27
  106. package/src/core/modules/better-auth/better-auth.resolver.ts +0 -11
  107. package/src/core/modules/better-auth/better-auth.service.ts +367 -12
  108. package/src/core/modules/better-auth/better-auth.types.ts +16 -0
  109. package/src/core/modules/better-auth/core-better-auth.controller.ts +44 -3
  110. package/src/core/modules/better-auth/core-better-auth.resolver.ts +136 -16
  111. package/src/core/modules/better-auth/index.ts +1 -0
  112. package/src/core/modules/user/core-user.service.ts +131 -4
  113. package/src/core/modules/user/interfaces/core-user-service-options.interface.ts +15 -0
  114. package/src/core.module.ts +264 -76
  115. package/src/index.ts +5 -0
  116. package/src/server/modules/auth/auth.resolver.ts +8 -0
  117. package/src/server/modules/better-auth/better-auth.module.ts +9 -3
  118. package/src/server/modules/better-auth/better-auth.resolver.ts +18 -11
  119. package/src/server/modules/user/user.controller.ts +1 -9
  120. package/src/server/modules/user/user.service.ts +4 -2
@@ -5,9 +5,11 @@ import { PassportModule } from '@nestjs/passport';
5
5
  import { PubSub } from 'graphql-subscriptions';
6
6
 
7
7
  import { AuthGuardStrategy } from './auth-guard-strategy.enum';
8
+ import { LegacyAuthRateLimitGuard } from './guards/legacy-auth-rate-limit.guard';
8
9
  import { RolesGuard } from './guards/roles.guard';
9
10
  import { CoreAuthUserService } from './services/core-auth-user.service';
10
11
  import { CoreAuthService } from './services/core-auth.service';
12
+ import { LegacyAuthRateLimiter } from './services/legacy-auth-rate-limiter.service';
11
13
  import { JwtRefreshStrategy } from './strategies/jwt-refresh.strategy';
12
14
  import { JwtStrategy } from './strategies/jwt.strategy';
13
15
 
@@ -68,6 +70,9 @@ export class CoreAuthModule {
68
70
  provide: JwtRefreshStrategy,
69
71
  useClass: options.jwtRefreshStrategy || JwtRefreshStrategy,
70
72
  },
73
+ // Rate limiting for Legacy Auth endpoints (disabled by default, configure via auth.rateLimit)
74
+ LegacyAuthRateLimiter,
75
+ LegacyAuthRateLimitGuard,
71
76
  ];
72
77
  if (Array.isArray(options?.providers)) {
73
78
  providers = imports.concat(options.providers);
@@ -75,7 +80,16 @@ export class CoreAuthModule {
75
80
 
76
81
  // Return CoreAuthModule
77
82
  return {
78
- exports: [CoreAuthService, JwtModule, JwtStrategy, JwtRefreshStrategy, PassportModule, UserModule],
83
+ exports: [
84
+ CoreAuthService,
85
+ JwtModule,
86
+ JwtStrategy,
87
+ JwtRefreshStrategy,
88
+ LegacyAuthRateLimiter,
89
+ LegacyAuthRateLimitGuard,
90
+ PassportModule,
91
+ UserModule,
92
+ ],
79
93
  imports,
80
94
  module: CoreAuthModule,
81
95
  providers,
@@ -10,7 +10,9 @@ import { ServiceOptions } from '../../common/interfaces/service-options.interfac
10
10
  import { ConfigService } from '../../common/services/config.service';
11
11
  import { AuthGuardStrategy } from './auth-guard-strategy.enum';
12
12
  import { CoreAuthModel } from './core-auth.model';
13
+ import { LegacyAuthDisabledException } from './exceptions/legacy-auth-disabled.exception';
13
14
  import { AuthGuard } from './guards/auth.guard';
15
+ import { LegacyAuthRateLimitGuard } from './guards/legacy-auth-rate-limit.guard';
14
16
  import { CoreAuthSignInInput } from './inputs/core-auth-sign-in.input';
15
17
  import { CoreAuthSignUpInput } from './inputs/core-auth-sign-up.input';
16
18
  import { ICoreAuthUser } from './interfaces/core-auth-user.interface';
@@ -19,6 +21,26 @@ import { Tokens } from './tokens.decorator';
19
21
 
20
22
  /**
21
23
  * Authentication resolver for the sign in
24
+ *
25
+ * This resolver provides Legacy Auth endpoints via GraphQL.
26
+ * In a future version, BetterAuth (IAM) will become the default.
27
+ *
28
+ * ## Disabling Legacy Endpoints
29
+ *
30
+ * After all users have migrated to BetterAuth (IAM), these endpoints
31
+ * can be disabled via configuration:
32
+ *
33
+ * ```typescript
34
+ * auth: {
35
+ * legacyEndpoints: {
36
+ * enabled: false, // Disable all legacy endpoints
37
+ * // or
38
+ * graphql: false // Disable only GraphQL endpoints
39
+ * }
40
+ * }
41
+ * ```
42
+ *
43
+ * @see https://github.com/lenneTech/nest-server/blob/develop/.claude/rules/module-deprecation.md
22
44
  */
23
45
  @Resolver(() => CoreAuthModel, { isAbstract: true })
24
46
  @Roles(RoleEnum.ADMIN)
@@ -31,67 +53,113 @@ export class CoreAuthResolver {
31
53
  protected readonly configService: ConfigService,
32
54
  ) {}
33
55
 
56
+ // ===========================================================================
57
+ // Helper - Legacy Endpoint Check
58
+ // ===========================================================================
59
+
60
+ /**
61
+ * Check if legacy GraphQL endpoints are enabled
62
+ *
63
+ * Throws LegacyAuthDisabledException if:
64
+ * - config.auth.legacyEndpoints.enabled is false
65
+ * - config.auth.legacyEndpoints.graphql is false
66
+ *
67
+ * @throws LegacyAuthDisabledException
68
+ */
69
+ protected checkLegacyGraphQLEnabled(endpointName: string): void {
70
+ const authConfig = this.configService.getFastButReadOnly('auth');
71
+ const legacyConfig = authConfig?.legacyEndpoints;
72
+
73
+ // Check if legacy endpoints are globally disabled
74
+ if (legacyConfig?.enabled === false) {
75
+ throw new LegacyAuthDisabledException(endpointName);
76
+ }
77
+
78
+ // Check if GraphQL endpoints specifically are disabled
79
+ if (legacyConfig?.graphql === false) {
80
+ throw new LegacyAuthDisabledException(endpointName);
81
+ }
82
+ }
83
+
34
84
  // ===========================================================================
35
85
  // Mutations
36
86
  // ===========================================================================
37
87
 
38
88
  /**
39
89
  * Logout user (from specific device)
90
+ *
91
+ * @deprecated Will be replaced by BetterAuth signOut in a future version
92
+ * @throws LegacyAuthDisabledException if legacy endpoints are disabled
40
93
  */
41
94
  @Mutation(() => Boolean, { description: 'Logout user (from specific device)' })
42
- @Roles(RoleEnum.S_EVERYONE)
43
- @UseGuards(AuthGuard(AuthGuardStrategy.JWT))
95
+ @Roles(RoleEnum.S_USER)
96
+ @UseGuards(LegacyAuthRateLimitGuard)
44
97
  async logout(
45
98
  @CurrentUser() currentUser: ICoreAuthUser,
46
99
  @Context() ctx: { res: ResponseType },
47
100
  @Tokens('token') token: string,
48
101
  @Args('allDevices', { nullable: true }) allDevices?: boolean,
49
102
  ): Promise<boolean> {
103
+ this.checkLegacyGraphQLEnabled('logout');
50
104
  const result = await this.authService.logout(token, { allDevices, currentUser });
51
105
  return this.processCookies(ctx, result);
52
106
  }
53
107
 
54
108
  /**
55
109
  * Refresh token (for specific device)
110
+ *
111
+ * @deprecated Will be replaced by BetterAuth session refresh in a future version
112
+ * @throws LegacyAuthDisabledException if legacy endpoints are disabled
56
113
  */
57
114
  @Mutation(() => CoreAuthModel, { description: 'Refresh tokens (for specific device)' })
58
115
  @Roles(RoleEnum.S_EVERYONE)
59
- @UseGuards(AuthGuard(AuthGuardStrategy.JWT_REFRESH))
116
+ @UseGuards(LegacyAuthRateLimitGuard, AuthGuard(AuthGuardStrategy.JWT_REFRESH))
60
117
  async refreshToken(
61
118
  @CurrentUser() user: ICoreAuthUser,
62
119
  @Tokens('refreshToken') refreshToken: string,
63
120
  @Context() ctx: { res: ResponseType },
64
121
  ): Promise<CoreAuthModel> {
122
+ this.checkLegacyGraphQLEnabled('refreshToken');
65
123
  const result = await this.authService.refreshTokens(user, refreshToken);
66
124
  return this.processCookies(ctx, result);
67
125
  }
68
126
 
69
127
  /**
70
128
  * Sign in user via email and password (on specific device)
129
+ *
130
+ * @deprecated Will be replaced by BetterAuth signIn in a future version
131
+ * @throws LegacyAuthDisabledException if legacy endpoints are disabled
71
132
  */
72
133
  @Mutation(() => CoreAuthModel, {
73
134
  description: 'Sign in user via email and password and get JWT tokens (for specific device)',
74
135
  })
75
136
  @Roles(RoleEnum.S_EVERYONE)
137
+ @UseGuards(LegacyAuthRateLimitGuard)
76
138
  async signIn(
77
139
  @GraphQLServiceOptions({ gqlPath: 'signIn.user' }) serviceOptions: ServiceOptions,
78
140
  @Context() ctx: { res: ResponseType },
79
141
  @Args('input') input: CoreAuthSignInInput,
80
142
  ): Promise<CoreAuthModel> {
143
+ this.checkLegacyGraphQLEnabled('signIn');
81
144
  const result = await this.authService.signIn(input, serviceOptions);
82
145
  return this.processCookies(ctx, result);
83
146
  }
84
147
 
85
148
  /**
86
149
  * Register a new user account (on specific device)
150
+ *
151
+ * @deprecated Will be replaced by BetterAuth signUp in a future version
152
+ * @throws LegacyAuthDisabledException if legacy endpoints are disabled
87
153
  */
88
154
  @Mutation(() => CoreAuthModel, { description: 'Register a new user account (on specific device)' })
89
155
  @Roles(RoleEnum.S_EVERYONE)
156
+ @UseGuards(LegacyAuthRateLimitGuard)
90
157
  async signUp(
91
158
  @GraphQLServiceOptions({ gqlPath: 'signUp.user' }) serviceOptions: ServiceOptions,
92
159
  @Context() ctx: { res: ResponseType },
93
160
  @Args('input') input: CoreAuthSignUpInput,
94
161
  ): Promise<CoreAuthModel> {
162
+ this.checkLegacyGraphQLEnabled('signUp');
95
163
  const result = await this.authService.signUp(input, serviceOptions);
96
164
  return this.processCookies(ctx, result);
97
165
  }
@@ -0,0 +1,35 @@
1
+ import { GoneException } from '@nestjs/common';
2
+
3
+ /**
4
+ * Exception thrown when Legacy Auth endpoints are accessed but disabled
5
+ *
6
+ * This exception is thrown when:
7
+ * - config.auth.legacyEndpoints.enabled is false
8
+ * - config.auth.legacyEndpoints.graphql is false (for GraphQL endpoints)
9
+ * - config.auth.legacyEndpoints.rest is false (for REST endpoints)
10
+ *
11
+ * HTTP Status: 410 Gone
12
+ *
13
+ * This status code indicates that the resource is no longer available
14
+ * and will not be available again - appropriate for deprecated endpoints.
15
+ *
16
+ * @since 11.7.1
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * if (!this.isLegacyEndpointEnabled()) {
21
+ * throw new LegacyAuthDisabledException();
22
+ * }
23
+ * ```
24
+ */
25
+ export class LegacyAuthDisabledException extends GoneException {
26
+ constructor(endpoint?: string) {
27
+ super({
28
+ error: 'Legacy Auth Disabled',
29
+ message: endpoint
30
+ ? `Legacy Auth endpoint '${endpoint}' is disabled. Use BetterAuth (IAM) endpoints instead.`
31
+ : 'Legacy Auth endpoints are disabled. Use BetterAuth (IAM) endpoints instead.',
32
+ statusCode: 410,
33
+ });
34
+ }
35
+ }
@@ -0,0 +1,109 @@
1
+ import { CanActivate, ExecutionContext, HttpException, HttpStatus, Injectable } from '@nestjs/common';
2
+ import { GqlExecutionContext } from '@nestjs/graphql';
3
+
4
+ import { LegacyAuthRateLimiter } from '../services/legacy-auth-rate-limiter.service';
5
+
6
+ /**
7
+ * Guard for rate limiting Legacy Auth endpoints
8
+ *
9
+ * This guard applies rate limiting to protect against brute-force attacks.
10
+ * It works with both REST and GraphQL endpoints.
11
+ *
12
+ * Rate limiting must be enabled via configuration:
13
+ * ```typescript
14
+ * auth: {
15
+ * rateLimit: {
16
+ * enabled: true,
17
+ * max: 10,
18
+ * windowSeconds: 60,
19
+ * }
20
+ * }
21
+ * ```
22
+ *
23
+ * @since 11.7.x
24
+ */
25
+ @Injectable()
26
+ export class LegacyAuthRateLimitGuard implements CanActivate {
27
+ constructor(private readonly rateLimiter: LegacyAuthRateLimiter) {}
28
+
29
+ canActivate(context: ExecutionContext): boolean {
30
+ // If rate limiting is disabled, always allow
31
+ if (!this.rateLimiter.isEnabled()) {
32
+ return true;
33
+ }
34
+
35
+ const { endpoint, ip } = this.extractRequestInfo(context);
36
+ const result = this.rateLimiter.check(ip, endpoint);
37
+
38
+ if (!result.allowed) {
39
+ throw new HttpException(
40
+ {
41
+ error: 'Too Many Requests',
42
+ message: this.rateLimiter.getMessage(),
43
+ remaining: result.remaining,
44
+ retryAfter: result.resetIn,
45
+ statusCode: HttpStatus.TOO_MANY_REQUESTS,
46
+ },
47
+ HttpStatus.TOO_MANY_REQUESTS,
48
+ );
49
+ }
50
+
51
+ return true;
52
+ }
53
+
54
+ /**
55
+ * Extract IP and endpoint from the execution context
56
+ */
57
+ private extractRequestInfo(context: ExecutionContext): { endpoint: string; ip: string } {
58
+ const contextType = context.getType<'graphql' | 'http'>();
59
+
60
+ if (contextType === 'graphql') {
61
+ const gqlContext = GqlExecutionContext.create(context);
62
+ const info = gqlContext.getInfo();
63
+ const ctx = gqlContext.getContext();
64
+
65
+ // Get IP from request
66
+ const req = ctx.req;
67
+ const ip = this.getClientIp(req);
68
+
69
+ // Get endpoint from GraphQL field name
70
+ const endpoint = info?.fieldName || 'unknown';
71
+
72
+ return { endpoint, ip };
73
+ }
74
+
75
+ // HTTP context
76
+ const request = context.switchToHttp().getRequest();
77
+ const ip = this.getClientIp(request);
78
+
79
+ // Get endpoint from URL path
80
+ const url = request.url || request.path || '';
81
+ const endpoint = url.split('/').pop() || 'unknown';
82
+
83
+ return { endpoint, ip };
84
+ }
85
+
86
+ /**
87
+ * Get client IP from request, handling proxies
88
+ */
89
+ private getClientIp(request: any): string {
90
+ if (!request) {
91
+ return 'unknown';
92
+ }
93
+
94
+ // Check common proxy headers
95
+ const forwardedFor = request.headers?.['x-forwarded-for'];
96
+ if (forwardedFor) {
97
+ // Take the first IP in the chain (original client)
98
+ return forwardedFor.split(',')[0].trim();
99
+ }
100
+
101
+ const realIp = request.headers?.['x-real-ip'];
102
+ if (realIp) {
103
+ return realIp;
104
+ }
105
+
106
+ // Fall back to direct connection IP
107
+ return request.ip || request.connection?.remoteAddress || 'unknown';
108
+ }
109
+ }
@@ -0,0 +1,86 @@
1
+ import { JwtPayload } from './jwt-payload.interface';
2
+
3
+ /**
4
+ * Auth Provider Interface
5
+ *
6
+ * This interface defines the contract for authentication providers.
7
+ * Both Legacy Auth (CoreAuthService) and BetterAuth can implement this interface,
8
+ * allowing CoreModule to work with either system transparently.
9
+ *
10
+ * @since 11.8.0
11
+ * @see https://github.com/lenneTech/nest-server/blob/develop/src/core/modules/auth/interfaces/auth-provider.interface.ts
12
+ *
13
+ * ## Roadmap
14
+ *
15
+ * ### v11.x (Current)
16
+ * - Interface introduced for future flexibility
17
+ * - Legacy Auth (CoreAuthService) is the default implementation
18
+ * - BetterAuth can be used alongside Legacy Auth
19
+ *
20
+ * ### Future Version (Planned)
21
+ * - CoreModule.forRoot will use IAuthProvider instead of concrete AuthService
22
+ * - Legacy Auth becomes optional (must be explicitly enabled)
23
+ * - BetterAuth becomes the recommended default
24
+ *
25
+ * ## Implementation Example
26
+ *
27
+ * ```typescript
28
+ * @Injectable()
29
+ * export class BetterAuthProvider implements IAuthProvider {
30
+ * constructor(private readonly betterAuthService: BetterAuthService) {}
31
+ *
32
+ * decodeJwt(token: string): JwtPayload {
33
+ * return this.betterAuthService.decodeJwt(token);
34
+ * }
35
+ *
36
+ * async validateUser(payload: JwtPayload): Promise<any> {
37
+ * return this.betterAuthService.validateUser(payload);
38
+ * }
39
+ *
40
+ * signToken(user: any, expiresIn?: string): string {
41
+ * return this.betterAuthService.signToken(user, expiresIn);
42
+ * }
43
+ * }
44
+ * ```
45
+ */
46
+ export interface IAuthProvider {
47
+ /**
48
+ * Decode a JWT token without verification
49
+ * Used for extracting payload information
50
+ *
51
+ * @param token - The JWT token to decode
52
+ * @returns The decoded JWT payload
53
+ */
54
+ decodeJwt(token: string): JwtPayload;
55
+
56
+ /**
57
+ * Sign a new JWT token for a user
58
+ *
59
+ * @param user - The user to create a token for
60
+ * @param expiresIn - Optional expiration time (e.g., '15m', '7d')
61
+ * @returns The signed JWT token
62
+ */
63
+ signToken(user: any, expiresIn?: string): string;
64
+
65
+ /**
66
+ * Validate a user based on JWT payload
67
+ * Called during authentication to verify the user exists and is valid
68
+ *
69
+ * @param payload - The JWT payload containing user information
70
+ * @returns The validated user object, or null if invalid
71
+ */
72
+ validateUser(payload: JwtPayload): Promise<any>;
73
+ }
74
+
75
+ /**
76
+ * Auth Provider Token for dependency injection
77
+ *
78
+ * Use this token to inject the auth provider in your services:
79
+ *
80
+ * ```typescript
81
+ * constructor(
82
+ * @Inject(AUTH_PROVIDER) private readonly authProvider: IAuthProvider,
83
+ * ) {}
84
+ * ```
85
+ */
86
+ export const AUTH_PROVIDER = 'AUTH_PROVIDER';
@@ -9,6 +9,12 @@ export interface ICoreAuthUser {
9
9
  */
10
10
  email: string;
11
11
 
12
+ /**
13
+ * Better-Auth (IAM) user ID for linking
14
+ * Set when user is migrated or created via IAM
15
+ */
16
+ iamId?: string;
17
+
12
18
  /**
13
19
  * ID of the user
14
20
  */