@lenne.tech/nest-server 11.8.0 → 11.10.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/dist/config.env.js +5 -0
- package/dist/config.env.js.map +1 -1
- package/dist/core/common/helpers/logging.helper.d.ts +6 -0
- package/dist/core/common/helpers/logging.helper.js +55 -0
- package/dist/core/common/helpers/logging.helper.js.map +1 -0
- package/dist/core/common/interfaces/server-options.interface.d.ts +50 -19
- package/dist/core/modules/auth/guards/roles.guard.js +37 -5
- package/dist/core/modules/auth/guards/roles.guard.js.map +1 -1
- package/dist/core/modules/auth/services/core-auth.service.d.ts +5 -5
- package/dist/core/modules/auth/services/core-auth.service.js +9 -8
- package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
- package/dist/core/modules/auth/tokens.decorator.d.ts +1 -1
- package/dist/core/modules/better-auth/better-auth.config.js +32 -10
- package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.resolver.d.ts +16 -16
- package/dist/core/modules/better-auth/better-auth.resolver.js +34 -34
- package/dist/core/modules/better-auth/better-auth.resolver.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.types.d.ts +2 -1
- package/dist/core/modules/better-auth/better-auth.types.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth-api.middleware.d.ts +10 -0
- package/dist/core/modules/better-auth/core-better-auth-api.middleware.js +91 -0
- package/dist/core/modules/better-auth/core-better-auth-api.middleware.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth-auth.model.d.ts +9 -0
- package/dist/core/modules/better-auth/{better-auth-auth.model.js → core-better-auth-auth.model.js} +17 -17
- package/dist/core/modules/better-auth/core-better-auth-auth.model.js.map +1 -0
- package/dist/core/modules/better-auth/{better-auth-migration-status.model.d.ts → core-better-auth-migration-status.model.d.ts} +1 -1
- package/dist/core/modules/better-auth/{better-auth-migration-status.model.js → core-better-auth-migration-status.model.js} +14 -14
- package/dist/core/modules/better-auth/core-better-auth-migration-status.model.js.map +1 -0
- package/dist/core/modules/better-auth/{better-auth-models.d.ts → core-better-auth-models.d.ts} +8 -8
- package/dist/core/modules/better-auth/{better-auth-models.js → core-better-auth-models.js} +61 -61
- package/dist/core/modules/better-auth/core-better-auth-models.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth-rate-limit.middleware.d.ts +12 -0
- package/dist/core/modules/better-auth/{better-auth-rate-limit.middleware.js → core-better-auth-rate-limit.middleware.js} +10 -10
- package/dist/core/modules/better-auth/core-better-auth-rate-limit.middleware.js.map +1 -0
- package/dist/core/modules/better-auth/{better-auth-rate-limiter.service.d.ts → core-better-auth-rate-limiter.service.d.ts} +1 -1
- package/dist/core/modules/better-auth/{better-auth-rate-limiter.service.js → core-better-auth-rate-limiter.service.js} +8 -8
- package/dist/core/modules/better-auth/core-better-auth-rate-limiter.service.js.map +1 -0
- package/dist/core/modules/better-auth/{better-auth-user.mapper.d.ts → core-better-auth-user.mapper.d.ts} +1 -1
- package/dist/core/modules/better-auth/{better-auth-user.mapper.js → core-better-auth-user.mapper.js} +10 -9
- package/dist/core/modules/better-auth/core-better-auth-user.mapper.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth-web.helper.d.ts +19 -0
- package/dist/core/modules/better-auth/core-better-auth-web.helper.js +152 -0
- package/dist/core/modules/better-auth/core-better-auth-web.helper.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth.controller.d.ts +23 -32
- package/dist/core/modules/better-auth/core-better-auth.controller.js +184 -201
- package/dist/core/modules/better-auth/core-better-auth.controller.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth.middleware.d.ts +22 -0
- package/dist/core/modules/better-auth/{better-auth.middleware.js → core-better-auth.middleware.js} +45 -18
- package/dist/core/modules/better-auth/core-better-auth.middleware.js.map +1 -0
- package/dist/core/modules/better-auth/{better-auth.module.d.ts → core-better-auth.module.d.ts} +6 -6
- package/dist/core/modules/better-auth/{better-auth.module.js → core-better-auth.module.js} +65 -60
- package/dist/core/modules/better-auth/core-better-auth.module.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth.resolver.d.ts +19 -19
- package/dist/core/modules/better-auth/core-better-auth.resolver.js +18 -18
- package/dist/core/modules/better-auth/core-better-auth.resolver.js.map +1 -1
- package/dist/core/modules/better-auth/{better-auth.service.d.ts → core-better-auth.service.d.ts} +3 -2
- package/dist/core/modules/better-auth/{better-auth.service.js → core-better-auth.service.js} +75 -35
- package/dist/core/modules/better-auth/core-better-auth.service.js.map +1 -0
- package/dist/core/modules/better-auth/index.d.ts +11 -9
- package/dist/core/modules/better-auth/index.js +11 -9
- package/dist/core/modules/better-auth/index.js.map +1 -1
- package/dist/core/modules/error-code/core-error-code.controller.d.ts +7 -0
- package/dist/core/modules/error-code/core-error-code.controller.js +45 -0
- package/dist/core/modules/error-code/core-error-code.controller.js.map +1 -0
- package/dist/core/modules/error-code/core-error-code.service.d.ts +16 -0
- package/dist/core/modules/error-code/core-error-code.service.js +65 -0
- package/dist/core/modules/error-code/core-error-code.service.js.map +1 -0
- package/dist/core/modules/error-code/error-code.module.d.ts +7 -0
- package/dist/core/modules/error-code/error-code.module.js +64 -0
- package/dist/core/modules/error-code/error-code.module.js.map +1 -0
- package/dist/core/modules/error-code/error-codes.d.ts +219 -0
- package/dist/core/modules/error-code/error-codes.js +204 -0
- package/dist/core/modules/error-code/error-codes.js.map +1 -0
- package/dist/core/modules/error-code/index.d.ts +5 -0
- package/dist/core/modules/error-code/index.js +22 -0
- package/dist/core/modules/error-code/index.js.map +1 -0
- package/dist/core/modules/error-code/interfaces/error-code.interfaces.d.ts +12 -0
- package/dist/core/modules/error-code/interfaces/error-code.interfaces.js +3 -0
- package/dist/core/modules/error-code/interfaces/error-code.interfaces.js.map +1 -0
- package/dist/core/modules/user/interfaces/core-user-service-options.interface.d.ts +2 -2
- package/dist/core.module.js +14 -6
- package/dist/core.module.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/server/modules/better-auth/better-auth.controller.d.ts +5 -5
- package/dist/server/modules/better-auth/better-auth.controller.js +4 -4
- package/dist/server/modules/better-auth/better-auth.controller.js.map +1 -1
- package/dist/server/modules/better-auth/better-auth.module.js +3 -3
- package/dist/server/modules/better-auth/better-auth.module.js.map +1 -1
- package/dist/server/modules/better-auth/better-auth.resolver.d.ts +17 -17
- package/dist/server/modules/better-auth/better-auth.resolver.js +18 -18
- package/dist/server/modules/better-auth/better-auth.resolver.js.map +1 -1
- package/dist/server/modules/error-code/error-code.controller.d.ts +8 -0
- package/dist/server/modules/error-code/error-code.controller.js +55 -0
- package/dist/server/modules/error-code/error-code.controller.js.map +1 -0
- package/dist/server/modules/error-code/error-code.service.d.ts +4 -0
- package/dist/server/modules/error-code/error-code.service.js +27 -0
- package/dist/server/modules/error-code/error-code.service.js.map +1 -0
- package/dist/server/modules/error-code/error-codes.d.ts +45 -0
- package/dist/server/modules/error-code/error-codes.js +24 -0
- package/dist/server/modules/error-code/error-codes.js.map +1 -0
- package/dist/server/modules/error-code/index.d.ts +3 -0
- package/dist/server/modules/error-code/index.js +20 -0
- package/dist/server/modules/error-code/index.js.map +1 -0
- package/dist/server/modules/user/user.service.d.ts +2 -2
- package/dist/server/modules/user/user.service.js +2 -2
- package/dist/server/modules/user/user.service.js.map +1 -1
- package/dist/server/server.module.js +7 -0
- package/dist/server/server.module.js.map +1 -1
- package/dist/test/test.helper.d.ts +1 -0
- package/dist/test/test.helper.js +5 -1
- package/dist/test/test.helper.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +6 -4
- package/src/config.env.ts +19 -0
- package/src/core/common/helpers/logging.helper.ts +134 -0
- package/src/core/common/interfaces/server-options.interface.ts +511 -237
- package/src/core/modules/auth/guards/roles.guard.ts +49 -7
- package/src/core/modules/auth/services/core-auth.service.ts +9 -8
- package/src/core/modules/better-auth/ARCHITECTURE.md +102 -0
- package/src/core/modules/better-auth/INTEGRATION-CHECKLIST.md +277 -8
- package/src/core/modules/better-auth/README.md +97 -53
- package/src/core/modules/better-auth/better-auth.config.ts +66 -18
- package/src/core/modules/better-auth/better-auth.resolver.ts +32 -32
- package/src/core/modules/better-auth/better-auth.types.ts +3 -2
- package/src/core/modules/better-auth/core-better-auth-api.middleware.ts +134 -0
- package/src/core/modules/better-auth/{better-auth-auth.model.ts → core-better-auth-auth.model.ts} +6 -6
- package/src/core/modules/better-auth/{better-auth-migration-status.model.ts → core-better-auth-migration-status.model.ts} +1 -1
- package/src/core/modules/better-auth/{better-auth-models.ts → core-better-auth-models.ts} +9 -9
- package/src/core/modules/better-auth/{better-auth-rate-limit.middleware.ts → core-better-auth-rate-limit.middleware.ts} +5 -5
- package/src/core/modules/better-auth/{better-auth-rate-limiter.service.ts → core-better-auth-rate-limiter.service.ts} +2 -2
- package/src/core/modules/better-auth/{better-auth-user.mapper.ts → core-better-auth-user.mapper.ts} +4 -3
- package/src/core/modules/better-auth/core-better-auth-web.helper.ts +272 -0
- package/src/core/modules/better-auth/core-better-auth.controller.ts +386 -230
- package/src/core/modules/better-auth/{better-auth.middleware.ts → core-better-auth.middleware.ts} +57 -17
- package/src/core/modules/better-auth/{better-auth.module.ts → core-better-auth.module.ts} +77 -66
- package/src/core/modules/better-auth/core-better-auth.resolver.ts +42 -42
- package/src/core/modules/better-auth/{better-auth.service.ts → core-better-auth.service.ts} +86 -40
- package/src/core/modules/better-auth/index.ts +18 -11
- package/src/core/modules/error-code/INTEGRATION-CHECKLIST.md +291 -0
- package/src/core/modules/error-code/core-error-code.controller.ts +55 -0
- package/src/core/modules/error-code/core-error-code.service.ts +135 -0
- package/src/core/modules/error-code/error-code.module.ts +119 -0
- package/src/core/modules/error-code/error-codes.ts +405 -0
- package/src/core/modules/error-code/index.ts +14 -0
- package/src/core/modules/error-code/interfaces/error-code.interfaces.ts +99 -0
- package/src/core/modules/user/interfaces/core-user-service-options.interface.ts +3 -3
- package/src/core.module.ts +28 -12
- package/src/index.ts +7 -0
- package/src/server/modules/better-auth/better-auth.controller.ts +4 -4
- package/src/server/modules/better-auth/better-auth.module.ts +1 -1
- package/src/server/modules/better-auth/better-auth.resolver.ts +31 -31
- package/src/server/modules/error-code/README.md +131 -0
- package/src/server/modules/error-code/error-code.controller.ts +91 -0
- package/src/server/modules/error-code/error-code.service.ts +42 -0
- package/src/server/modules/error-code/error-codes.ts +65 -0
- package/src/server/modules/error-code/index.ts +8 -0
- package/src/server/modules/user/user.service.ts +2 -2
- package/src/server/server.module.ts +10 -0
- package/src/test/test.helper.ts +13 -1
- package/dist/core/modules/better-auth/better-auth-auth.model.d.ts +0 -9
- package/dist/core/modules/better-auth/better-auth-auth.model.js.map +0 -1
- package/dist/core/modules/better-auth/better-auth-migration-status.model.js.map +0 -1
- package/dist/core/modules/better-auth/better-auth-models.js.map +0 -1
- package/dist/core/modules/better-auth/better-auth-rate-limit.middleware.d.ts +0 -12
- package/dist/core/modules/better-auth/better-auth-rate-limit.middleware.js.map +0 -1
- package/dist/core/modules/better-auth/better-auth-rate-limiter.service.js.map +0 -1
- package/dist/core/modules/better-auth/better-auth-user.mapper.js.map +0 -1
- package/dist/core/modules/better-auth/better-auth.middleware.d.ts +0 -21
- package/dist/core/modules/better-auth/better-auth.middleware.js.map +0 -1
- package/dist/core/modules/better-auth/better-auth.module.js.map +0 -1
- package/dist/core/modules/better-auth/better-auth.service.js.map +0 -1
package/src/core/modules/better-auth/{better-auth.middleware.ts → core-better-auth.middleware.ts}
RENAMED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { Injectable, Logger, NestMiddleware } from '@nestjs/common';
|
|
2
2
|
import { NextFunction, Request, Response } from 'express';
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { isProduction, maskEmail, maskToken } from '../../common/helpers/logging.helper';
|
|
5
|
+
import { BetterAuthSessionUser, CoreBetterAuthUserMapper, MappedUser } from './core-better-auth-user.mapper';
|
|
6
|
+
import { extractSessionToken } from './core-better-auth-web.helper';
|
|
7
|
+
import { CoreBetterAuthService } from './core-better-auth.service';
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* Extended Express Request with Better-Auth session data
|
|
9
11
|
*/
|
|
10
|
-
export interface
|
|
12
|
+
export interface CoreBetterAuthRequest extends Request {
|
|
11
13
|
betterAuthSession?: {
|
|
12
14
|
session: any;
|
|
13
15
|
user: BetterAuthSessionUser;
|
|
@@ -29,15 +31,16 @@ export interface BetterAuthRequest extends Request {
|
|
|
29
31
|
* for RolesGuard and other security checks.
|
|
30
32
|
*/
|
|
31
33
|
@Injectable()
|
|
32
|
-
export class
|
|
33
|
-
private readonly logger = new Logger(
|
|
34
|
+
export class CoreBetterAuthMiddleware implements NestMiddleware {
|
|
35
|
+
private readonly logger = new Logger(CoreBetterAuthMiddleware.name);
|
|
36
|
+
private readonly isProd = isProduction();
|
|
34
37
|
|
|
35
38
|
constructor(
|
|
36
|
-
private readonly betterAuthService:
|
|
37
|
-
private readonly userMapper:
|
|
39
|
+
private readonly betterAuthService: CoreBetterAuthService,
|
|
40
|
+
private readonly userMapper: CoreBetterAuthUserMapper,
|
|
38
41
|
) {}
|
|
39
42
|
|
|
40
|
-
async use(req:
|
|
43
|
+
async use(req: CoreBetterAuthRequest, _res: Response, next: NextFunction) {
|
|
41
44
|
// Skip if Better-Auth is not enabled
|
|
42
45
|
if (!this.betterAuthService.isEnabled()) {
|
|
43
46
|
return next();
|
|
@@ -79,7 +82,7 @@ export class BetterAuthMiddleware implements NestMiddleware {
|
|
|
79
82
|
// Check if token looks like a JWT (has 3 parts)
|
|
80
83
|
if (tokenParts === 3) {
|
|
81
84
|
// Decode JWT payload to check if it's a Legacy JWT or BetterAuth JWT
|
|
82
|
-
// Legacy JWTs have 'id' claim, BetterAuth JWTs
|
|
85
|
+
// Legacy JWTs have 'id' claim, BetterAuth JWTs use 'sub'
|
|
83
86
|
const isLegacyJwt = this.isLegacyJwt(token);
|
|
84
87
|
if (isLegacyJwt) {
|
|
85
88
|
// Legacy JWT - skip BetterAuth processing, let Passport handle it
|
|
@@ -131,7 +134,9 @@ export class BetterAuthMiddleware implements NestMiddleware {
|
|
|
131
134
|
} catch (error) {
|
|
132
135
|
// Don't block the request on auth errors
|
|
133
136
|
// The guards will handle unauthorized access
|
|
134
|
-
this.
|
|
137
|
+
if (!this.isProd) {
|
|
138
|
+
this.logger.debug(`Session validation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
139
|
+
}
|
|
135
140
|
}
|
|
136
141
|
|
|
137
142
|
next();
|
|
@@ -159,15 +164,48 @@ export class BetterAuthMiddleware implements NestMiddleware {
|
|
|
159
164
|
}
|
|
160
165
|
|
|
161
166
|
/**
|
|
162
|
-
* Gets the session from Better-Auth
|
|
167
|
+
* Gets the session from Better-Auth using session token from cookies
|
|
168
|
+
*
|
|
169
|
+
* This method first tries to extract the session token from cookies
|
|
170
|
+
* (checking multiple cookie names for compatibility), then validates
|
|
171
|
+
* the session directly from the database using getSessionByToken().
|
|
163
172
|
*/
|
|
164
173
|
private async getSession(req: Request): Promise<null | { session: any; user: BetterAuthSessionUser }> {
|
|
165
|
-
const api = this.betterAuthService.getApi();
|
|
166
|
-
if (!api) {
|
|
167
|
-
return null;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
174
|
try {
|
|
175
|
+
// Strategy 1: Try to get session token from cookies using shared helper
|
|
176
|
+
const basePath = this.betterAuthService.getBasePath();
|
|
177
|
+
const sessionToken = extractSessionToken(req, basePath);
|
|
178
|
+
|
|
179
|
+
if (!this.isProd) {
|
|
180
|
+
this.logger.debug(`[MIDDLEWARE] getSession called, token found: ${sessionToken ? 'yes' : 'no'}`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (sessionToken) {
|
|
184
|
+
if (!this.isProd) {
|
|
185
|
+
this.logger.debug(`[MIDDLEWARE] Found session token in cookies: ${maskToken(sessionToken)}`);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Use getSessionByToken to validate session directly from database
|
|
189
|
+
const sessionResult = await this.betterAuthService.getSessionByToken(sessionToken);
|
|
190
|
+
|
|
191
|
+
if (!this.isProd) {
|
|
192
|
+
this.logger.debug(`[MIDDLEWARE] getSessionByToken result: user=${maskEmail(sessionResult?.user?.email)}, session=${!!sessionResult?.session}`);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (sessionResult?.user && sessionResult?.session) {
|
|
196
|
+
if (!this.isProd) {
|
|
197
|
+
this.logger.debug(`[MIDDLEWARE] Session validated for user: ${maskEmail(sessionResult.user.email)}`);
|
|
198
|
+
}
|
|
199
|
+
return sessionResult as { session: any; user: BetterAuthSessionUser };
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Strategy 2: Fallback to api.getSession() for edge cases
|
|
204
|
+
const api = this.betterAuthService.getApi();
|
|
205
|
+
if (!api) {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
|
|
171
209
|
// Convert Express headers to the format Better-Auth expects
|
|
172
210
|
const headers = new Headers();
|
|
173
211
|
for (const [key, value] of Object.entries(req.headers)) {
|
|
@@ -187,7 +225,9 @@ export class BetterAuthMiddleware implements NestMiddleware {
|
|
|
187
225
|
|
|
188
226
|
return null;
|
|
189
227
|
} catch (error) {
|
|
190
|
-
this.
|
|
228
|
+
if (!this.isProd) {
|
|
229
|
+
this.logger.debug(`getSession error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
230
|
+
}
|
|
191
231
|
return null;
|
|
192
232
|
}
|
|
193
233
|
}
|
|
@@ -14,15 +14,16 @@ import mongoose, { Connection } from 'mongoose';
|
|
|
14
14
|
|
|
15
15
|
import { IBetterAuth } from '../../common/interfaces/server-options.interface';
|
|
16
16
|
import { ConfigService } from '../../common/services/config.service';
|
|
17
|
-
import { BetterAuthRateLimitMiddleware } from './better-auth-rate-limit.middleware';
|
|
18
|
-
import { BetterAuthRateLimiter } from './better-auth-rate-limiter.service';
|
|
19
|
-
import { BetterAuthUserMapper } from './better-auth-user.mapper';
|
|
20
17
|
import { BetterAuthInstance, createBetterAuthInstance } from './better-auth.config';
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
18
|
+
import { DefaultBetterAuthResolver } from './better-auth.resolver';
|
|
19
|
+
import { CoreBetterAuthApiMiddleware } from './core-better-auth-api.middleware';
|
|
20
|
+
import { CoreBetterAuthRateLimitMiddleware } from './core-better-auth-rate-limit.middleware';
|
|
21
|
+
import { CoreBetterAuthRateLimiter } from './core-better-auth-rate-limiter.service';
|
|
22
|
+
import { CoreBetterAuthUserMapper } from './core-better-auth-user.mapper';
|
|
24
23
|
import { CoreBetterAuthController } from './core-better-auth.controller';
|
|
24
|
+
import { CoreBetterAuthMiddleware } from './core-better-auth.middleware';
|
|
25
25
|
import { CoreBetterAuthResolver } from './core-better-auth.resolver';
|
|
26
|
+
import { BETTER_AUTH_CONFIG, CoreBetterAuthService } from './core-better-auth.service';
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
29
|
* Token for injecting the better-auth instance
|
|
@@ -30,9 +31,9 @@ import { CoreBetterAuthResolver } from './core-better-auth.resolver';
|
|
|
30
31
|
export const BETTER_AUTH_INSTANCE = 'BETTER_AUTH_INSTANCE';
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
|
-
* Options for
|
|
34
|
+
* Options for CoreBetterAuthModule.forRoot()
|
|
34
35
|
*/
|
|
35
|
-
export interface
|
|
36
|
+
export interface CoreBetterAuthModuleOptions {
|
|
36
37
|
/**
|
|
37
38
|
* Better-auth configuration.
|
|
38
39
|
* Accepts:
|
|
@@ -59,7 +60,7 @@ export interface BetterAuthModuleOptions {
|
|
|
59
60
|
* }
|
|
60
61
|
*
|
|
61
62
|
* // In your module
|
|
62
|
-
*
|
|
63
|
+
* CoreBetterAuthModule.forRoot({
|
|
63
64
|
* config: environment.betterAuth,
|
|
64
65
|
* controller: MyBetterAuthController,
|
|
65
66
|
* })
|
|
@@ -79,14 +80,14 @@ export interface BetterAuthModuleOptions {
|
|
|
79
80
|
fallbackSecrets?: (string | undefined)[];
|
|
80
81
|
|
|
81
82
|
/**
|
|
82
|
-
* Custom resolver class to use instead of the default
|
|
83
|
+
* Custom resolver class to use instead of the default DefaultBetterAuthResolver.
|
|
83
84
|
* The class must extend CoreBetterAuthResolver.
|
|
84
85
|
*
|
|
85
86
|
* @example
|
|
86
87
|
* ```typescript
|
|
87
88
|
* // Your custom resolver
|
|
88
89
|
* @Resolver(() => BetterAuthAuthModel)
|
|
89
|
-
* export class
|
|
90
|
+
* export class MyDefaultBetterAuthResolver extends CoreBetterAuthResolver {
|
|
90
91
|
* override async betterAuthSignUp(...) {
|
|
91
92
|
* const result = await super.betterAuthSignUp(...);
|
|
92
93
|
* await this.sendWelcomeEmail(result.user);
|
|
@@ -95,9 +96,9 @@ export interface BetterAuthModuleOptions {
|
|
|
95
96
|
* }
|
|
96
97
|
*
|
|
97
98
|
* // In your module
|
|
98
|
-
*
|
|
99
|
+
* CoreBetterAuthModule.forRoot({
|
|
99
100
|
* config: environment.betterAuth,
|
|
100
|
-
* resolver:
|
|
101
|
+
* resolver: MyDefaultBetterAuthResolver,
|
|
101
102
|
* })
|
|
102
103
|
* ```
|
|
103
104
|
*/
|
|
@@ -119,7 +120,7 @@ function normalizeBetterAuthConfig(config: boolean | IBetterAuth | undefined): I
|
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
/**
|
|
122
|
-
*
|
|
123
|
+
* CoreBetterAuthModule provides integration with the better-auth authentication framework.
|
|
123
124
|
*
|
|
124
125
|
* This module:
|
|
125
126
|
* - Creates and configures a better-auth instance based on server configuration
|
|
@@ -134,7 +135,7 @@ function normalizeBetterAuthConfig(config: boolean | IBetterAuth | undefined): I
|
|
|
134
135
|
* @Module({
|
|
135
136
|
* imports: [
|
|
136
137
|
* CoreModule.forRoot(...),
|
|
137
|
-
*
|
|
138
|
+
* CoreBetterAuthModule.forRoot({ config: environment.betterAuth }),
|
|
138
139
|
* ],
|
|
139
140
|
* })
|
|
140
141
|
* export class AppModule {}
|
|
@@ -142,8 +143,8 @@ function normalizeBetterAuthConfig(config: boolean | IBetterAuth | undefined): I
|
|
|
142
143
|
*/
|
|
143
144
|
@Global()
|
|
144
145
|
@Module({})
|
|
145
|
-
export class
|
|
146
|
-
private static logger = new Logger(
|
|
146
|
+
export class CoreBetterAuthModule implements NestModule, OnModuleInit {
|
|
147
|
+
private static logger = new Logger(CoreBetterAuthModule.name);
|
|
147
148
|
private static authInstance: BetterAuthInstance | null = null;
|
|
148
149
|
private static initialized = false;
|
|
149
150
|
private static initLogged = false;
|
|
@@ -163,45 +164,53 @@ export class BetterAuthModule implements NestModule, OnModuleInit {
|
|
|
163
164
|
* Gets the resolver class to use (custom or default)
|
|
164
165
|
*/
|
|
165
166
|
private static getResolverClass(): Type<CoreBetterAuthResolver> {
|
|
166
|
-
return this.customResolver ||
|
|
167
|
+
return this.customResolver || DefaultBetterAuthResolver;
|
|
167
168
|
}
|
|
168
169
|
|
|
169
170
|
constructor(
|
|
170
|
-
@Optional() private readonly betterAuthService?:
|
|
171
|
-
@Optional() private readonly rateLimiter?:
|
|
171
|
+
@Optional() private readonly betterAuthService?: CoreBetterAuthService,
|
|
172
|
+
@Optional() private readonly rateLimiter?: CoreBetterAuthRateLimiter,
|
|
172
173
|
) {}
|
|
173
174
|
|
|
174
175
|
onModuleInit() {
|
|
175
|
-
if (
|
|
176
|
-
|
|
177
|
-
|
|
176
|
+
if (CoreBetterAuthModule.authInstance && !CoreBetterAuthModule.initialized) {
|
|
177
|
+
CoreBetterAuthModule.initialized = true;
|
|
178
|
+
CoreBetterAuthModule.logger.log('CoreBetterAuthModule ready');
|
|
178
179
|
}
|
|
179
180
|
|
|
180
181
|
// Configure rate limiter with stored config
|
|
181
|
-
if (this.rateLimiter &&
|
|
182
|
-
this.rateLimiter.configure(
|
|
182
|
+
if (this.rateLimiter && CoreBetterAuthModule.currentConfig?.rateLimit) {
|
|
183
|
+
this.rateLimiter.configure(CoreBetterAuthModule.currentConfig.rateLimit);
|
|
183
184
|
}
|
|
184
185
|
}
|
|
185
186
|
|
|
186
187
|
/**
|
|
187
|
-
* Configure middleware for Better-Auth
|
|
188
|
-
*
|
|
189
|
-
*
|
|
188
|
+
* Configure middleware for Better-Auth API handling, session validation, and rate limiting.
|
|
189
|
+
*
|
|
190
|
+
* Middleware order (important!):
|
|
191
|
+
* 1. CoreBetterAuthApiMiddleware - Forwards plugin endpoints (passkey, etc.) to Better Auth's native handler
|
|
192
|
+
* 2. CoreBetterAuthRateLimitMiddleware - Rate limiting for auth endpoints
|
|
193
|
+
* 3. CoreBetterAuthMiddleware - Session validation and user mapping for all routes
|
|
190
194
|
*/
|
|
191
195
|
configure(consumer: MiddlewareConsumer) {
|
|
192
196
|
// Only apply middleware if Better-Auth is enabled
|
|
193
|
-
if (
|
|
194
|
-
const basePath =
|
|
197
|
+
if (CoreBetterAuthModule.betterAuthEnabled && this.betterAuthService?.isEnabled()) {
|
|
198
|
+
const basePath = CoreBetterAuthModule.currentConfig?.basePath || '/iam';
|
|
199
|
+
|
|
200
|
+
// Apply API middleware to Better-Auth endpoints FIRST
|
|
201
|
+
// This handles plugin endpoints (passkey, social login, etc.) that are not defined in the controller
|
|
202
|
+
consumer.apply(CoreBetterAuthApiMiddleware).forRoutes(`${basePath}/*path`);
|
|
203
|
+
CoreBetterAuthModule.logger.debug(`CoreBetterAuthApiMiddleware registered for ${basePath}/*path endpoints`);
|
|
195
204
|
|
|
196
205
|
// Apply rate limiting to Better-Auth endpoints only
|
|
197
|
-
if (
|
|
198
|
-
consumer.apply(
|
|
199
|
-
|
|
206
|
+
if (CoreBetterAuthModule.currentConfig?.rateLimit?.enabled) {
|
|
207
|
+
consumer.apply(CoreBetterAuthRateLimitMiddleware).forRoutes(`${basePath}/*path`);
|
|
208
|
+
CoreBetterAuthModule.logger.debug(`Rate limiting middleware registered for ${basePath}/*path endpoints`);
|
|
200
209
|
}
|
|
201
210
|
|
|
202
211
|
// Apply session middleware to all routes
|
|
203
|
-
consumer.apply(
|
|
204
|
-
|
|
212
|
+
consumer.apply(CoreBetterAuthMiddleware).forRoutes('(.*)'); // New path-to-regexp syntax for wildcard
|
|
213
|
+
CoreBetterAuthModule.logger.debug('CoreBetterAuthMiddleware registered for all routes');
|
|
205
214
|
}
|
|
206
215
|
}
|
|
207
216
|
|
|
@@ -241,7 +250,7 @@ export class BetterAuthModule implements NestModule, OnModuleInit {
|
|
|
241
250
|
* @param options - Configuration options
|
|
242
251
|
* @returns Dynamic module configuration
|
|
243
252
|
*/
|
|
244
|
-
static forRoot(options:
|
|
253
|
+
static forRoot(options: CoreBetterAuthModuleOptions): DynamicModule {
|
|
245
254
|
const { config: rawConfig, controller, fallbackSecrets, resolver } = options;
|
|
246
255
|
|
|
247
256
|
// Normalize config: true → {}, false/undefined → null
|
|
@@ -255,14 +264,14 @@ export class BetterAuthModule implements NestModule, OnModuleInit {
|
|
|
255
264
|
this.customResolver = resolver || null;
|
|
256
265
|
|
|
257
266
|
// If better-auth is disabled (config is null or enabled: false), return minimal module
|
|
258
|
-
// Note: We don't provide middleware classes when disabled because they depend on
|
|
267
|
+
// Note: We don't provide middleware classes when disabled because they depend on CoreBetterAuthService
|
|
259
268
|
// and won't be used anyway (middleware is only applied when enabled)
|
|
260
269
|
if (config === null || config?.enabled === false) {
|
|
261
270
|
this.logger.debug('BetterAuth is disabled - skipping initialization');
|
|
262
271
|
this.betterAuthEnabled = false;
|
|
263
272
|
return {
|
|
264
|
-
exports: [BETTER_AUTH_INSTANCE,
|
|
265
|
-
module:
|
|
273
|
+
exports: [BETTER_AUTH_INSTANCE, CoreBetterAuthService, CoreBetterAuthUserMapper, CoreBetterAuthRateLimiter],
|
|
274
|
+
module: CoreBetterAuthModule,
|
|
266
275
|
providers: [
|
|
267
276
|
{
|
|
268
277
|
provide: BETTER_AUTH_INSTANCE,
|
|
@@ -270,9 +279,9 @@ export class BetterAuthModule implements NestModule, OnModuleInit {
|
|
|
270
279
|
},
|
|
271
280
|
// Note: ConfigService is provided globally by CoreModule
|
|
272
281
|
// Tests need to provide their own ConfigService
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
282
|
+
CoreBetterAuthService,
|
|
283
|
+
CoreBetterAuthUserMapper,
|
|
284
|
+
CoreBetterAuthRateLimiter,
|
|
276
285
|
],
|
|
277
286
|
};
|
|
278
287
|
}
|
|
@@ -297,9 +306,9 @@ export class BetterAuthModule implements NestModule, OnModuleInit {
|
|
|
297
306
|
static forRootAsync(): DynamicModule {
|
|
298
307
|
return {
|
|
299
308
|
controllers: [this.getControllerClass()],
|
|
300
|
-
exports: [BETTER_AUTH_INSTANCE,
|
|
309
|
+
exports: [BETTER_AUTH_INSTANCE, CoreBetterAuthService, CoreBetterAuthUserMapper, CoreBetterAuthRateLimiter],
|
|
301
310
|
imports: [],
|
|
302
|
-
module:
|
|
311
|
+
module: CoreBetterAuthModule,
|
|
303
312
|
providers: [
|
|
304
313
|
{
|
|
305
314
|
inject: [ConfigService],
|
|
@@ -337,7 +346,7 @@ export class BetterAuthModule implements NestModule, OnModuleInit {
|
|
|
337
346
|
this.authInstance = createBetterAuthInstance({ config, db, fallbackSecrets });
|
|
338
347
|
|
|
339
348
|
// IMPORTANT: Store the config AFTER createBetterAuthInstance mutates it
|
|
340
|
-
// This ensures
|
|
349
|
+
// This ensures CoreBetterAuthService has access to the resolved secret (with fallback applied)
|
|
341
350
|
this.currentConfig = config;
|
|
342
351
|
|
|
343
352
|
if (this.authInstance) {
|
|
@@ -348,28 +357,29 @@ export class BetterAuthModule implements NestModule, OnModuleInit {
|
|
|
348
357
|
return this.authInstance;
|
|
349
358
|
},
|
|
350
359
|
},
|
|
351
|
-
// Provide the resolved config for
|
|
360
|
+
// Provide the resolved config for CoreBetterAuthService
|
|
352
361
|
{
|
|
353
362
|
provide: BETTER_AUTH_CONFIG,
|
|
354
363
|
useFactory: () => this.currentConfig,
|
|
355
364
|
},
|
|
356
|
-
//
|
|
365
|
+
// CoreBetterAuthService needs to be a factory that explicitly depends on BETTER_AUTH_INSTANCE
|
|
357
366
|
// to ensure proper initialization order
|
|
358
367
|
{
|
|
359
368
|
inject: [BETTER_AUTH_INSTANCE, BETTER_AUTH_CONFIG, getConnectionToken()],
|
|
360
|
-
provide:
|
|
369
|
+
provide: CoreBetterAuthService,
|
|
361
370
|
useFactory: (
|
|
362
371
|
authInstance: BetterAuthInstance | null,
|
|
363
372
|
resolvedConfig: IBetterAuth | null,
|
|
364
373
|
connection: Connection,
|
|
365
374
|
) => {
|
|
366
|
-
return new
|
|
375
|
+
return new CoreBetterAuthService(authInstance, connection, resolvedConfig);
|
|
367
376
|
},
|
|
368
377
|
},
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
378
|
+
CoreBetterAuthUserMapper,
|
|
379
|
+
CoreBetterAuthMiddleware,
|
|
380
|
+
CoreBetterAuthApiMiddleware,
|
|
381
|
+
CoreBetterAuthRateLimiter,
|
|
382
|
+
CoreBetterAuthRateLimitMiddleware,
|
|
373
383
|
this.getResolverClass(),
|
|
374
384
|
],
|
|
375
385
|
};
|
|
@@ -384,13 +394,13 @@ export class BetterAuthModule implements NestModule, OnModuleInit {
|
|
|
384
394
|
}
|
|
385
395
|
|
|
386
396
|
/**
|
|
387
|
-
* Resets the static state of
|
|
397
|
+
* Resets the static state of CoreBetterAuthModule
|
|
388
398
|
* This is primarily useful for testing to ensure clean state between tests
|
|
389
399
|
*
|
|
390
400
|
* @example
|
|
391
401
|
* ```typescript
|
|
392
402
|
* afterEach(() => {
|
|
393
|
-
*
|
|
403
|
+
* CoreBetterAuthModule.reset();
|
|
394
404
|
* });
|
|
395
405
|
* ```
|
|
396
406
|
*/
|
|
@@ -411,8 +421,8 @@ export class BetterAuthModule implements NestModule, OnModuleInit {
|
|
|
411
421
|
private static createDeferredModule(config: IBetterAuth, fallbackSecrets?: (string | undefined)[]): DynamicModule {
|
|
412
422
|
return {
|
|
413
423
|
controllers: [this.getControllerClass()],
|
|
414
|
-
exports: [BETTER_AUTH_INSTANCE,
|
|
415
|
-
module:
|
|
424
|
+
exports: [BETTER_AUTH_INSTANCE, CoreBetterAuthService, CoreBetterAuthUserMapper, CoreBetterAuthRateLimiter],
|
|
425
|
+
module: CoreBetterAuthModule,
|
|
416
426
|
providers: [
|
|
417
427
|
{
|
|
418
428
|
// Inject Mongoose Connection to ensure NestJS waits for it to be ready
|
|
@@ -434,7 +444,7 @@ export class BetterAuthModule implements NestModule, OnModuleInit {
|
|
|
434
444
|
}
|
|
435
445
|
|
|
436
446
|
// IMPORTANT: Store the config AFTER createBetterAuthInstance mutates it
|
|
437
|
-
// This ensures
|
|
447
|
+
// This ensures CoreBetterAuthService has access to the resolved secret (with fallback applied)
|
|
438
448
|
this.currentConfig = config;
|
|
439
449
|
|
|
440
450
|
if (this.authInstance && !this.initLogged) {
|
|
@@ -446,28 +456,29 @@ export class BetterAuthModule implements NestModule, OnModuleInit {
|
|
|
446
456
|
return this.authInstance;
|
|
447
457
|
},
|
|
448
458
|
},
|
|
449
|
-
// Provide the resolved config for
|
|
459
|
+
// Provide the resolved config for CoreBetterAuthService
|
|
450
460
|
{
|
|
451
461
|
provide: BETTER_AUTH_CONFIG,
|
|
452
462
|
useFactory: () => this.currentConfig,
|
|
453
463
|
},
|
|
454
|
-
//
|
|
464
|
+
// CoreBetterAuthService needs to be a factory that explicitly depends on BETTER_AUTH_INSTANCE
|
|
455
465
|
// to ensure proper initialization order
|
|
456
466
|
{
|
|
457
467
|
inject: [BETTER_AUTH_INSTANCE, BETTER_AUTH_CONFIG, getConnectionToken()],
|
|
458
|
-
provide:
|
|
468
|
+
provide: CoreBetterAuthService,
|
|
459
469
|
useFactory: (
|
|
460
470
|
authInstance: BetterAuthInstance | null,
|
|
461
471
|
resolvedConfig: IBetterAuth | null,
|
|
462
472
|
connection: Connection,
|
|
463
473
|
) => {
|
|
464
|
-
return new
|
|
474
|
+
return new CoreBetterAuthService(authInstance, connection, resolvedConfig);
|
|
465
475
|
},
|
|
466
476
|
},
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
477
|
+
CoreBetterAuthUserMapper,
|
|
478
|
+
CoreBetterAuthMiddleware,
|
|
479
|
+
CoreBetterAuthApiMiddleware,
|
|
480
|
+
CoreBetterAuthRateLimiter,
|
|
481
|
+
CoreBetterAuthRateLimitMiddleware,
|
|
471
482
|
this.getResolverClass(),
|
|
472
483
|
],
|
|
473
484
|
};
|