@lenne.tech/nest-server 11.26.1 → 11.26.3

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 (32) hide show
  1. package/FRAMEWORK-API.md +1 -1
  2. package/dist/core/common/decorators/unified-field.decorator.js +2 -7
  3. package/dist/core/common/decorators/unified-field.decorator.js.map +1 -1
  4. package/dist/core/modules/better-auth/better-auth-cookie-prefix.helper.d.ts +3 -0
  5. package/dist/core/modules/better-auth/better-auth-cookie-prefix.helper.js +27 -0
  6. package/dist/core/modules/better-auth/better-auth-cookie-prefix.helper.js.map +1 -0
  7. package/dist/core/modules/better-auth/better-auth.config.d.ts +1 -1
  8. package/dist/core/modules/better-auth/better-auth.config.js +13 -1
  9. package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
  10. package/dist/core/modules/better-auth/core-better-auth-cookie.helper.js +2 -1
  11. package/dist/core/modules/better-auth/core-better-auth-cookie.helper.js.map +1 -1
  12. package/dist/core/modules/better-auth/core-better-auth-web.helper.js +3 -4
  13. package/dist/core/modules/better-auth/core-better-auth-web.helper.js.map +1 -1
  14. package/dist/core/modules/better-auth/core-better-auth.controller.js +1 -2
  15. package/dist/core/modules/better-auth/core-better-auth.controller.js.map +1 -1
  16. package/dist/core/modules/better-auth/core-better-auth.service.d.ts +2 -0
  17. package/dist/core/modules/better-auth/core-better-auth.service.js +10 -4
  18. package/dist/core/modules/better-auth/core-better-auth.service.js.map +1 -1
  19. package/dist/test/test.helper.js +5 -3
  20. package/dist/test/test.helper.js.map +1 -1
  21. package/dist/tsconfig.build.tsbuildinfo +1 -1
  22. package/migration-guides/11.26.1-to-11.26.2.md +234 -0
  23. package/migration-guides/11.26.2-to-11.26.3.md +186 -0
  24. package/package.json +1 -1
  25. package/src/core/common/decorators/unified-field.decorator.ts +13 -7
  26. package/src/core/modules/better-auth/better-auth-cookie-prefix.helper.ts +84 -0
  27. package/src/core/modules/better-auth/better-auth.config.ts +34 -3
  28. package/src/core/modules/better-auth/core-better-auth-cookie.helper.ts +12 -2
  29. package/src/core/modules/better-auth/core-better-auth-web.helper.ts +6 -7
  30. package/src/core/modules/better-auth/core-better-auth.controller.ts +1 -2
  31. package/src/core/modules/better-auth/core-better-auth.service.ts +29 -4
  32. package/src/test/test.helper.ts +13 -3
@@ -2,6 +2,7 @@ import { Logger } from '@nestjs/common';
2
2
  import * as crypto from 'crypto';
3
3
  import { Request, Response } from 'express';
4
4
 
5
+ import { resolveBetterAuthSessionCookieName } from './better-auth-cookie-prefix.helper';
5
6
  import { isSessionToken } from './core-better-auth-token.helper';
6
7
 
7
8
  /**
@@ -94,13 +95,12 @@ export function extractSessionToken(
94
95
  }
95
96
  }
96
97
 
97
- // Normalize basePath (remove leading slash, replace slashes with dots)
98
- const normalizedBasePath = basePath.replace(/^\//, '').replace(/\//g, '.');
99
-
100
98
  // Cookie names to check (in order of priority)
101
- // v11.12+: Only native Better-Auth cookie and legacy token
99
+ // v11.12+: Only native Better-Auth cookie and legacy token. The session cookie
100
+ // name is resolved through the single shared resolver (honours COOKIE_PREFIX),
101
+ // so it always matches what Better-Auth actually sets.
102
102
  const cookieNames = [
103
- `${normalizedBasePath}.session_token`, // Better-Auth native (PRIMARY)
103
+ resolveBetterAuthSessionCookieName(basePath), // Better-Auth native (PRIMARY)
104
104
  BETTER_AUTH_COOKIE_NAMES.TOKEN, // Legacy nest-server cookie
105
105
  ];
106
106
 
@@ -320,8 +320,7 @@ export async function toWebRequest(req: Request, options: ToWebRequestOptions):
320
320
  if (sessionToken) {
321
321
  headers.set('authorization', `Bearer ${sessionToken}`);
322
322
 
323
- const normalizedBasePath = basePath?.replace(/^\//, '').replace(/\//g, '.') || 'iam';
324
- const primaryCookieName = `${normalizedBasePath}.session_token`;
323
+ const primaryCookieName = resolveBetterAuthSessionCookieName(basePath || '/iam');
325
324
  const existingCookieString = headers.get('cookie') || '';
326
325
 
327
326
  // Check if the request already has a signed session cookie.
@@ -776,8 +776,7 @@ export class CoreBetterAuthController {
776
776
  }
777
777
 
778
778
  // Check cookies - Better-Auth native cookie first, then legacy token
779
- const basePath = this.betterAuthService.getBasePath().replace(/^\//, '').replace(/\//g, '.');
780
- const cookieName = `${basePath}.session_token`;
779
+ const cookieName = this.betterAuthService.getSessionCookieName();
781
780
  return req.cookies?.[cookieName] || req.cookies?.['token'] || null;
782
781
  }
783
782
 
@@ -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
- const basePath = this.getBasePath()?.replace(/^\//, '').replace(/\//g, '.') || 'iam';
284
- return `${basePath}.session_token`;
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 basePath = this.getBasePath()?.replace(/^\//, '').replace(/\//g, '.') || 'iam';
438
- const sessionCookieName = `${basePath}.session_token`;
463
+ const sessionCookieName = this.getSessionCookieName();
439
464
  const cookies = parseCookieHeader(cookieHeader);
440
465
  let modified = false;
441
466
 
@@ -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
- [`${basePath}.session_token`]: sessionToken,
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: string = 'iam.session_token'): null | string {
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[cookieName];
877
+ const value = cookies[resolvedCookieName];
868
878
  if (!value) {
869
879
  return null;
870
880
  }