@lenne.tech/nest-server 11.26.0 → 11.26.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.
- package/FRAMEWORK-API.md +1 -1
- package/dist/core/modules/better-auth/better-auth-cookie-prefix.helper.d.ts +3 -0
- package/dist/core/modules/better-auth/better-auth-cookie-prefix.helper.js +27 -0
- package/dist/core/modules/better-auth/better-auth-cookie-prefix.helper.js.map +1 -0
- package/dist/core/modules/better-auth/better-auth.config.d.ts +1 -1
- package/dist/core/modules/better-auth/better-auth.config.js +13 -1
- package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth-cookie.helper.js +2 -1
- package/dist/core/modules/better-auth/core-better-auth-cookie.helper.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth-web.helper.js +3 -4
- package/dist/core/modules/better-auth/core-better-auth-web.helper.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth.controller.d.ts +2 -1
- package/dist/core/modules/better-auth/core-better-auth.controller.js +13 -3
- package/dist/core/modules/better-auth/core-better-auth.controller.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth.service.d.ts +2 -0
- package/dist/core/modules/better-auth/core-better-auth.service.js +10 -4
- package/dist/core/modules/better-auth/core-better-auth.service.js.map +1 -1
- package/dist/test/test.helper.js +5 -3
- package/dist/test/test.helper.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/migration-guides/11.26.0-to-11.26.1.md +193 -0
- package/migration-guides/11.26.1-to-11.26.2.md +234 -0
- package/package.json +1 -1
- package/src/core/modules/better-auth/better-auth-cookie-prefix.helper.ts +84 -0
- package/src/core/modules/better-auth/better-auth.config.ts +34 -3
- package/src/core/modules/better-auth/core-better-auth-cookie.helper.ts +12 -2
- package/src/core/modules/better-auth/core-better-auth-web.helper.ts +6 -7
- package/src/core/modules/better-auth/core-better-auth.controller.ts +21 -5
- package/src/core/modules/better-auth/core-better-auth.service.ts +29 -4
- package/src/test/test.helper.ts +13 -3
|
@@ -75,6 +75,14 @@ export class CoreBetterAuthUserResponse {
|
|
|
75
75
|
@ApiProperty({ description: 'User display name' })
|
|
76
76
|
name: string;
|
|
77
77
|
|
|
78
|
+
@ApiProperty({
|
|
79
|
+
description: 'Roles of the user (e.g. ["admin"]) — populated from the synced legacy user.',
|
|
80
|
+
isArray: true,
|
|
81
|
+
required: false,
|
|
82
|
+
type: String,
|
|
83
|
+
})
|
|
84
|
+
roles?: string[];
|
|
85
|
+
|
|
78
86
|
@ApiProperty({ description: 'Whether 2FA is enabled', required: false })
|
|
79
87
|
twoFactorEnabled?: boolean;
|
|
80
88
|
}
|
|
@@ -768,8 +776,7 @@ export class CoreBetterAuthController {
|
|
|
768
776
|
}
|
|
769
777
|
|
|
770
778
|
// Check cookies - Better-Auth native cookie first, then legacy token
|
|
771
|
-
const
|
|
772
|
-
const cookieName = `${basePath}.session_token`;
|
|
779
|
+
const cookieName = this.betterAuthService.getSessionCookieName();
|
|
773
780
|
return req.cookies?.[cookieName] || req.cookies?.['token'] || null;
|
|
774
781
|
}
|
|
775
782
|
|
|
@@ -799,16 +806,25 @@ export class CoreBetterAuthController {
|
|
|
799
806
|
|
|
800
807
|
/**
|
|
801
808
|
* Map user to response format
|
|
809
|
+
*
|
|
810
|
+
* The `mappedUser` parameter is the synced legacy user from `mapSessionUser()` — it
|
|
811
|
+
* carries DB-only fields like `roles` that are not part of the Better-Auth session
|
|
812
|
+
* payload but are required by consumers for admin gating / RBAC. The base
|
|
813
|
+
* implementation forwards `roles` so the client-side state (`useLtAuth().setUser()`
|
|
814
|
+
* cache, `lt-auth-state` cookie) can route admin areas without a second round-trip.
|
|
815
|
+
*
|
|
816
|
+
* Subclasses can override to add project-specific fields (e.g. `status`, `type`).
|
|
817
|
+
*
|
|
802
818
|
* @param sessionUser - The user from Better-Auth session
|
|
803
|
-
* @param
|
|
819
|
+
* @param mappedUser - The synced user from legacy system (includes `roles`)
|
|
804
820
|
*/
|
|
805
|
-
|
|
806
|
-
protected mapUser(sessionUser: BetterAuthSessionUser, _mappedUser: any): CoreBetterAuthUserResponse {
|
|
821
|
+
protected mapUser(sessionUser: BetterAuthSessionUser, mappedUser: any): CoreBetterAuthUserResponse {
|
|
807
822
|
return {
|
|
808
823
|
email: sessionUser.email,
|
|
809
824
|
emailVerified: sessionUser.emailVerified || false,
|
|
810
825
|
id: sessionUser.id,
|
|
811
826
|
name: sessionUser.name || sessionUser.email.split('@')[0],
|
|
827
|
+
roles: Array.isArray(mappedUser?.roles) ? mappedUser.roles : [],
|
|
812
828
|
};
|
|
813
829
|
}
|
|
814
830
|
|
|
@@ -9,6 +9,7 @@ import { maskEmail, maskToken } from '../../common/helpers/logging.helper';
|
|
|
9
9
|
import { IBetterAuth, ICookiesConfig } from '../../common/interfaces/server-options.interface';
|
|
10
10
|
import { ConfigService } from '../../common/services/config.service';
|
|
11
11
|
import { ErrorCode } from '../error-code/error-codes';
|
|
12
|
+
import { resolveBetterAuthCookiePrefix } from './better-auth-cookie-prefix.helper';
|
|
12
13
|
import { BetterAuthInstance } from './better-auth.config';
|
|
13
14
|
import { BetterAuthSessionUser } from './core-better-auth-user.mapper';
|
|
14
15
|
import { convertExpressHeaders, parseCookieHeader, signCookieValueIfNeeded } from './core-better-auth-web.helper';
|
|
@@ -65,6 +66,11 @@ export const BETTER_AUTH_COOKIE_DOMAIN = 'BETTER_AUTH_COOKIE_DOMAIN';
|
|
|
65
66
|
export class CoreBetterAuthService implements OnModuleInit {
|
|
66
67
|
private readonly logger = new Logger(CoreBetterAuthService.name);
|
|
67
68
|
private readonly config: IBetterAuth;
|
|
69
|
+
// Cached cookie prefix — frozen on first read so the value cannot drift away
|
|
70
|
+
// from the Better-Auth instance (which captured it at bootstrap). Without
|
|
71
|
+
// this cache a test or fork that mutates `process.env.COOKIE_PREFIX` after
|
|
72
|
+
// boot would push the service and the Better-Auth instance out of lockstep.
|
|
73
|
+
private cachedCookiePrefix: null | string = null;
|
|
68
74
|
|
|
69
75
|
constructor(
|
|
70
76
|
@Optional() @Inject(BETTER_AUTH_INSTANCE) private readonly authInstance: BetterAuthInstance | null,
|
|
@@ -280,8 +286,28 @@ export class CoreBetterAuthService implements OnModuleInit {
|
|
|
280
286
|
* @returns The session cookie name
|
|
281
287
|
*/
|
|
282
288
|
getSessionCookieName(): string {
|
|
283
|
-
|
|
284
|
-
|
|
289
|
+
return `${this.getCookiePrefix()}.session_token`;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Gets the cookie prefix (the `iam` in `iam.session_token`).
|
|
294
|
+
*
|
|
295
|
+
* Single source of truth: honours the `COOKIE_PREFIX` env override and falls
|
|
296
|
+
* back to the basePath-derived prefix. Every session-cookie call site must
|
|
297
|
+
* resolve the name through this (or {@link getSessionCookieName}) so the name
|
|
298
|
+
* stays in lockstep across the whole auth pipeline.
|
|
299
|
+
*
|
|
300
|
+
* The resolved value is cached on first read and reused for the lifetime of
|
|
301
|
+
* the service so it cannot drift away from the Better-Auth instance, which
|
|
302
|
+
* captures the prefix once at bootstrap. A late mutation of
|
|
303
|
+
* `process.env.COOKIE_PREFIX` (typical in tests / forked workers) would
|
|
304
|
+
* otherwise make set, read and clear use different names.
|
|
305
|
+
*/
|
|
306
|
+
getCookiePrefix(): string {
|
|
307
|
+
if (this.cachedCookiePrefix === null) {
|
|
308
|
+
this.cachedCookiePrefix = resolveBetterAuthCookiePrefix(this.getBasePath() || '/iam');
|
|
309
|
+
}
|
|
310
|
+
return this.cachedCookiePrefix;
|
|
285
311
|
}
|
|
286
312
|
|
|
287
313
|
// ===================================================================================================================
|
|
@@ -434,8 +460,7 @@ export class CoreBetterAuthService implements OnModuleInit {
|
|
|
434
460
|
// Browser clients send unsigned cookies, but Better-Auth expects signed cookies
|
|
435
461
|
const cookieHeader = headers.get('cookie');
|
|
436
462
|
if (cookieHeader && this.config?.secret) {
|
|
437
|
-
const
|
|
438
|
-
const sessionCookieName = `${basePath}.session_token`;
|
|
463
|
+
const sessionCookieName = this.getSessionCookieName();
|
|
439
464
|
const cookies = parseCookieHeader(cookieHeader);
|
|
440
465
|
let modified = false;
|
|
441
466
|
|
package/src/test/test.helper.ts
CHANGED
|
@@ -8,6 +8,7 @@ import util = require('util');
|
|
|
8
8
|
import ws = require('ws');
|
|
9
9
|
|
|
10
10
|
import { getStringIds } from '../core/common/helpers/db.helper';
|
|
11
|
+
import { resolveBetterAuthSessionCookieName } from '../core/modules/better-auth/better-auth-cookie-prefix.helper';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* GraphQL request type
|
|
@@ -830,8 +831,11 @@ export class TestHelper {
|
|
|
830
831
|
* Sets the token in all relevant cookie names for compatibility.
|
|
831
832
|
*/
|
|
832
833
|
static buildBetterAuthCookies(sessionToken: string, basePath: string = 'iam'): Record<string, string> {
|
|
834
|
+
// Resolve the session cookie name through the shared resolver so tests honour
|
|
835
|
+
// a COOKIE_PREFIX override exactly like the runtime (otherwise an authenticated
|
|
836
|
+
// request in a COOKIE_PREFIX=acme app would send the wrong cookie name).
|
|
833
837
|
return {
|
|
834
|
-
[
|
|
838
|
+
[resolveBetterAuthSessionCookieName(basePath)]: sessionToken,
|
|
835
839
|
token: sessionToken,
|
|
836
840
|
};
|
|
837
841
|
}
|
|
@@ -861,10 +865,16 @@ export class TestHelper {
|
|
|
861
865
|
/**
|
|
862
866
|
* Extract a session token from Set-Cookie headers of a supertest response.
|
|
863
867
|
* Handles signed cookies (value.signature format) by returning only the value part.
|
|
868
|
+
*
|
|
869
|
+
* The default cookie name is resolved through the shared resolver so it
|
|
870
|
+
* honours a `COOKIE_PREFIX` env override exactly like the runtime (otherwise
|
|
871
|
+
* tests against a `COOKIE_PREFIX=acme` app would look for the wrong cookie
|
|
872
|
+
* and silently return `null`). Tests can still pass an explicit name.
|
|
864
873
|
*/
|
|
865
|
-
static extractSessionToken(response: any, cookieName
|
|
874
|
+
static extractSessionToken(response: any, cookieName?: string): null | string {
|
|
875
|
+
const resolvedCookieName = cookieName ?? resolveBetterAuthSessionCookieName('/iam');
|
|
866
876
|
const cookies = TestHelper.extractCookies(response);
|
|
867
|
-
const value = cookies[
|
|
877
|
+
const value = cookies[resolvedCookieName];
|
|
868
878
|
if (!value) {
|
|
869
879
|
return null;
|
|
870
880
|
}
|