@flusys/nestjs-auth 1.1.0-beta → 2.0.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.
Files changed (86) hide show
  1. package/README.md +590 -473
  2. package/cjs/config/auth.constants.js +8 -0
  3. package/cjs/controllers/authentication.controller.js +218 -39
  4. package/cjs/controllers/branch.controller.js +44 -1
  5. package/cjs/controllers/company-selection.controller.js +27 -20
  6. package/cjs/controllers/company.controller.js +44 -1
  7. package/cjs/controllers/user-permission.controller.js +82 -154
  8. package/cjs/controllers/user.controller.js +68 -15
  9. package/cjs/docs/auth-swagger.config.js +14 -7
  10. package/cjs/dtos/authentication.dto.js +16 -43
  11. package/cjs/dtos/index.js +0 -1
  12. package/cjs/dtos/user-permission.dto.js +28 -0
  13. package/cjs/dtos/user.dto.js +19 -4
  14. package/cjs/entities/user-company-permission.entity.js +0 -6
  15. package/cjs/interceptors/clear-token.interceptor.js +10 -23
  16. package/cjs/interceptors/set-token.interceptor.js +15 -55
  17. package/cjs/interfaces/auth-email-provider.interface.js +1 -1
  18. package/cjs/modules/auth.module.js +63 -147
  19. package/cjs/services/auth-config.service.js +22 -28
  20. package/cjs/services/auth-datasource.provider.js +9 -21
  21. package/cjs/services/auth-email.service.js +89 -85
  22. package/cjs/services/authentication.service.js +225 -396
  23. package/cjs/services/branch.service.js +9 -4
  24. package/cjs/services/company-selection-session.service.js +1 -1
  25. package/cjs/services/user-permission.service.js +43 -73
  26. package/cjs/services/user.service.js +78 -64
  27. package/cjs/strategies/jwt.strategy.js +44 -44
  28. package/cjs/validators/password.validator.js +45 -0
  29. package/config/auth.constants.d.ts +2 -0
  30. package/controllers/authentication.controller.d.ts +5 -3
  31. package/controllers/company-selection.controller.d.ts +6 -2
  32. package/controllers/user-permission.controller.d.ts +5 -4
  33. package/controllers/user.controller.d.ts +6 -0
  34. package/dtos/authentication.dto.d.ts +0 -4
  35. package/dtos/company-branch.dto.d.ts +0 -1
  36. package/dtos/company.dto.d.ts +0 -1
  37. package/dtos/index.d.ts +0 -1
  38. package/dtos/user-permission.dto.d.ts +4 -0
  39. package/dtos/user.dto.d.ts +1 -3
  40. package/entities/index.d.ts +3 -3
  41. package/entities/user-company-permission.entity.d.ts +0 -2
  42. package/fesm/config/auth.constants.js +6 -13
  43. package/fesm/controllers/authentication.controller.js +221 -42
  44. package/fesm/controllers/branch.controller.js +45 -2
  45. package/fesm/controllers/company-selection.controller.js +28 -21
  46. package/fesm/controllers/company.controller.js +45 -2
  47. package/fesm/controllers/user-permission.controller.js +84 -156
  48. package/fesm/controllers/user.controller.js +71 -18
  49. package/fesm/docs/auth-swagger.config.js +14 -7
  50. package/fesm/dtos/authentication.dto.js +17 -44
  51. package/fesm/dtos/index.js +0 -1
  52. package/fesm/dtos/user-permission.dto.js +28 -0
  53. package/fesm/dtos/user.dto.js +20 -5
  54. package/fesm/entities/user-company-permission.entity.js +0 -6
  55. package/fesm/interceptors/clear-token.interceptor.js +9 -22
  56. package/fesm/interceptors/set-token.interceptor.js +14 -54
  57. package/fesm/interfaces/auth-email-provider.interface.js +1 -1
  58. package/fesm/modules/auth.module.js +64 -148
  59. package/fesm/services/auth-config.service.js +23 -29
  60. package/fesm/services/auth-datasource.provider.js +10 -22
  61. package/fesm/services/auth-email.service.js +90 -86
  62. package/fesm/services/authentication.service.js +225 -396
  63. package/fesm/services/branch.service.js +9 -4
  64. package/fesm/services/company-selection-session.service.js +1 -1
  65. package/fesm/services/user-permission.service.js +44 -74
  66. package/fesm/services/user.service.js +79 -65
  67. package/fesm/strategies/jwt.strategy.js +44 -44
  68. package/fesm/validators/password.validator.js +48 -0
  69. package/interceptors/clear-token.interceptor.d.ts +0 -1
  70. package/interceptors/set-token.interceptor.d.ts +1 -1
  71. package/interfaces/authentication.interface.d.ts +0 -4
  72. package/interfaces/user-enricher.interface.d.ts +1 -4
  73. package/modules/auth.module.d.ts +6 -3
  74. package/package.json +4 -4
  75. package/services/auth-config.service.d.ts +6 -8
  76. package/services/auth-datasource.provider.d.ts +2 -4
  77. package/services/auth-email.service.d.ts +8 -4
  78. package/services/authentication.service.d.ts +15 -16
  79. package/services/company-selection-session.service.d.ts +1 -1
  80. package/services/user-permission.service.d.ts +6 -9
  81. package/services/user.service.d.ts +3 -0
  82. package/strategies/jwt.strategy.d.ts +4 -1
  83. package/validators/password.validator.d.ts +10 -0
  84. package/cjs/dtos/user-company-permission.dto.js +0 -110
  85. package/dtos/user-company-permission.dto.d.ts +0 -10
  86. package/fesm/dtos/user-company-permission.dto.js +0 -98
@@ -72,6 +72,7 @@ _export(exports, {
72
72
  });
73
73
  const _swagger = require("@nestjs/swagger");
74
74
  const _classvalidator = require("class-validator");
75
+ const _passwordvalidator = require("../validators/password.validator");
75
76
  function _define_property(obj, key, value) {
76
77
  if (key in obj) {
77
78
  Object.defineProperty(obj, key, {
@@ -111,12 +112,12 @@ _ts_decorate([
111
112
  ], LoginDto.prototype, "email", void 0);
112
113
  _ts_decorate([
113
114
  (0, _swagger.ApiProperty)({
114
- example: '123456',
115
- description: 'User password (min 6 chars)'
115
+ example: 'SecureP@ss1',
116
+ description: 'User password'
116
117
  }),
117
118
  (0, _classvalidator.IsString)(),
118
119
  (0, _classvalidator.IsNotEmpty)(),
119
- (0, _classvalidator.MinLength)(6),
120
+ (0, _classvalidator.MaxLength)(128),
120
121
  _ts_metadata("design:type", String)
121
122
  ], LoginDto.prototype, "password", void 0);
122
123
  let RegistrationDto = class RegistrationDto {
@@ -155,13 +156,13 @@ _ts_decorate([
155
156
  ], RegistrationDto.prototype, "email", void 0);
156
157
  _ts_decorate([
157
158
  (0, _swagger.ApiProperty)({
158
- example: 'strongPassword123',
159
- description: 'Password (min 6 chars)'
159
+ example: 'StrongP@ss123',
160
+ description: 'Password (min 8 chars, requires uppercase, lowercase, number, special char)'
160
161
  }),
161
162
  (0, _classvalidator.IsNotEmpty)(),
162
163
  (0, _classvalidator.IsString)(),
163
- (0, _classvalidator.MinLength)(6),
164
- (0, _classvalidator.MaxLength)(60),
164
+ (0, _passwordvalidator.IsStrongPassword)(),
165
+ (0, _classvalidator.MaxLength)(128),
165
166
  _ts_metadata("design:type", String)
166
167
  ], RegistrationDto.prototype, "password", void 0);
167
168
  _ts_decorate([
@@ -222,6 +223,7 @@ _ts_decorate([
222
223
  }),
223
224
  (0, _classvalidator.IsOptional)(),
224
225
  (0, _classvalidator.IsString)(),
226
+ (0, _classvalidator.MaxLength)(500),
225
227
  _ts_metadata("design:type", String)
226
228
  ], RegistrationDto.prototype, "newCompanyAddress", void 0);
227
229
  let RefreshTokenDto = class RefreshTokenDto {
@@ -251,16 +253,17 @@ _ts_decorate([
251
253
  }),
252
254
  (0, _classvalidator.IsString)(),
253
255
  (0, _classvalidator.IsNotEmpty)(),
256
+ (0, _classvalidator.MaxLength)(128),
254
257
  _ts_metadata("design:type", String)
255
258
  ], ChangePasswordDto.prototype, "currentPassword", void 0);
256
259
  _ts_decorate([
257
260
  (0, _swagger.ApiProperty)({
258
- example: 'newPassword456',
259
- description: 'New password (min 6 chars)'
261
+ example: 'NewP@ssword456',
262
+ description: 'New password (min 8 chars, requires uppercase, lowercase, number, special char)'
260
263
  }),
261
264
  (0, _classvalidator.IsString)(),
262
265
  (0, _classvalidator.IsNotEmpty)(),
263
- (0, _classvalidator.MinLength)(6),
266
+ (0, _passwordvalidator.IsStrongPassword)(),
264
267
  _ts_metadata("design:type", String)
265
268
  ], ChangePasswordDto.prototype, "newPassword", void 0);
266
269
  let SelectDto = class SelectDto {
@@ -428,7 +431,6 @@ let BranchSelectionInfoDto = class BranchSelectionInfoDto {
428
431
  _define_property(this, "id", void 0);
429
432
  _define_property(this, "name", void 0);
430
433
  _define_property(this, "slug", void 0);
431
- _define_property(this, "isActive", void 0);
432
434
  _define_property(this, "logoId", void 0);
433
435
  }
434
436
  };
@@ -450,12 +452,6 @@ _ts_decorate([
450
452
  }),
451
453
  _ts_metadata("design:type", String)
452
454
  ], BranchSelectionInfoDto.prototype, "slug", void 0);
453
- _ts_decorate([
454
- (0, _swagger.ApiProperty)({
455
- example: true
456
- }),
457
- _ts_metadata("design:type", Boolean)
458
- ], BranchSelectionInfoDto.prototype, "isActive", void 0);
459
455
  _ts_decorate([
460
456
  (0, _swagger.ApiPropertyOptional)({
461
457
  example: '550e8400-e29b-41d4-a716-446655440077',
@@ -469,7 +465,6 @@ let CompanyWithBranchesDto = class CompanyWithBranchesDto {
469
465
  _define_property(this, "id", void 0);
470
466
  _define_property(this, "name", void 0);
471
467
  _define_property(this, "slug", void 0);
472
- _define_property(this, "isActive", void 0);
473
468
  _define_property(this, "logoId", void 0);
474
469
  _define_property(this, "branches", void 0);
475
470
  }
@@ -492,12 +487,6 @@ _ts_decorate([
492
487
  }),
493
488
  _ts_metadata("design:type", String)
494
489
  ], CompanyWithBranchesDto.prototype, "slug", void 0);
495
- _ts_decorate([
496
- (0, _swagger.ApiProperty)({
497
- example: true
498
- }),
499
- _ts_metadata("design:type", Boolean)
500
- ], CompanyWithBranchesDto.prototype, "isActive", void 0);
501
490
  _ts_decorate([
502
491
  (0, _swagger.ApiPropertyOptional)({
503
492
  example: '550e8400-e29b-41d4-a716-446655440088',
@@ -522,7 +511,6 @@ let LoginResponseDto = class LoginResponseDto {
522
511
  _define_property(this, "user", void 0);
523
512
  _define_property(this, "company", void 0);
524
513
  _define_property(this, "branch", void 0);
525
- _define_property(this, "companyFeatureEnabled", void 0);
526
514
  }
527
515
  };
528
516
  _ts_decorate([
@@ -558,13 +546,6 @@ _ts_decorate([
558
546
  }),
559
547
  _ts_metadata("design:type", typeof BranchInfoDto === "undefined" ? Object : BranchInfoDto)
560
548
  ], LoginResponseDto.prototype, "branch", void 0);
561
- _ts_decorate([
562
- (0, _swagger.ApiPropertyOptional)({
563
- example: true,
564
- description: 'Whether company feature is enabled'
565
- }),
566
- _ts_metadata("design:type", Boolean)
567
- ], LoginResponseDto.prototype, "companyFeatureEnabled", void 0);
568
549
  let RegistrationResponseDto = class RegistrationResponseDto {
569
550
  constructor(){
570
551
  _define_property(this, "accessToken", void 0);
@@ -572,7 +553,6 @@ let RegistrationResponseDto = class RegistrationResponseDto {
572
553
  _define_property(this, "user", void 0);
573
554
  _define_property(this, "company", void 0);
574
555
  _define_property(this, "branch", void 0);
575
- _define_property(this, "companyFeatureEnabled", void 0);
576
556
  _define_property(this, "requiresEmailVerification", void 0);
577
557
  }
578
558
  };
@@ -609,13 +589,6 @@ _ts_decorate([
609
589
  }),
610
590
  _ts_metadata("design:type", typeof BranchInfoDto === "undefined" ? Object : BranchInfoDto)
611
591
  ], RegistrationResponseDto.prototype, "branch", void 0);
612
- _ts_decorate([
613
- (0, _swagger.ApiPropertyOptional)({
614
- example: true,
615
- description: 'Whether company feature is enabled'
616
- }),
617
- _ts_metadata("design:type", Boolean)
618
- ], RegistrationResponseDto.prototype, "companyFeatureEnabled", void 0);
619
592
  _ts_decorate([
620
593
  (0, _swagger.ApiPropertyOptional)({
621
594
  example: true,
@@ -753,12 +726,12 @@ _ts_decorate([
753
726
  ], ResetPasswordDto.prototype, "token", void 0);
754
727
  _ts_decorate([
755
728
  (0, _swagger.ApiProperty)({
756
- example: 'newSecurePassword123',
757
- description: 'New password (min 6 chars)'
729
+ example: 'NewSecureP@ss123',
730
+ description: 'New password (min 8 chars, requires uppercase, lowercase, number, special char)'
758
731
  }),
759
732
  (0, _classvalidator.IsString)(),
760
733
  (0, _classvalidator.IsNotEmpty)(),
761
- (0, _classvalidator.MinLength)(6),
734
+ (0, _passwordvalidator.IsStrongPassword)(),
762
735
  _ts_metadata("design:type", String)
763
736
  ], ResetPasswordDto.prototype, "newPassword", void 0);
764
737
  let VerifyEmailDto = class VerifyEmailDto {
package/cjs/dtos/index.js CHANGED
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  _export_star(require("./authentication.dto"), exports);
6
6
  _export_star(require("./company-branch.dto"), exports);
7
7
  _export_star(require("./company.dto"), exports);
8
- _export_star(require("./user-company-permission.dto"), exports);
9
8
  _export_star(require("./user.dto"), exports);
10
9
  _export_star(require("./user-permission.dto"), exports);
11
10
  function _export_star(from, to) {
@@ -254,9 +254,23 @@ _ts_decorate([
254
254
  ], UserBranchPermissionDto.prototype, "companyId", void 0);
255
255
  let UserCompaniesResponseDto = class UserCompaniesResponseDto {
256
256
  constructor(){
257
+ _define_property(this, "success", void 0);
258
+ _define_property(this, "message", void 0);
257
259
  _define_property(this, "data", void 0);
258
260
  }
259
261
  };
262
+ _ts_decorate([
263
+ (0, _swagger.ApiProperty)({
264
+ example: true
265
+ }),
266
+ _ts_metadata("design:type", Boolean)
267
+ ], UserCompaniesResponseDto.prototype, "success", void 0);
268
+ _ts_decorate([
269
+ (0, _swagger.ApiProperty)({
270
+ example: 'User companies retrieved successfully'
271
+ }),
272
+ _ts_metadata("design:type", String)
273
+ ], UserCompaniesResponseDto.prototype, "message", void 0);
260
274
  _ts_decorate([
261
275
  (0, _swagger.ApiProperty)({
262
276
  description: 'List of companies the user has access to',
@@ -284,9 +298,23 @@ _ts_decorate([
284
298
  ], UserCompaniesResponseDto.prototype, "data", void 0);
285
299
  let UserBranchesResponseDto = class UserBranchesResponseDto {
286
300
  constructor(){
301
+ _define_property(this, "success", void 0);
302
+ _define_property(this, "message", void 0);
287
303
  _define_property(this, "data", void 0);
288
304
  }
289
305
  };
306
+ _ts_decorate([
307
+ (0, _swagger.ApiProperty)({
308
+ example: true
309
+ }),
310
+ _ts_metadata("design:type", Boolean)
311
+ ], UserBranchesResponseDto.prototype, "success", void 0);
312
+ _ts_decorate([
313
+ (0, _swagger.ApiProperty)({
314
+ example: 'User branches retrieved successfully'
315
+ }),
316
+ _ts_metadata("design:type", String)
317
+ ], UserBranchesResponseDto.prototype, "message", void 0);
290
318
  _ts_decorate([
291
319
  (0, _swagger.ApiProperty)({
292
320
  description: 'List of branches the user has access to',
@@ -21,6 +21,7 @@ _export(exports, {
21
21
  });
22
22
  const _swagger = require("@nestjs/swagger");
23
23
  const _classvalidator = require("class-validator");
24
+ const _passwordvalidator = require("../validators/password.validator");
24
25
  function _define_property(obj, key, value) {
25
26
  if (key in obj) {
26
27
  Object.defineProperty(obj, key, {
@@ -83,10 +84,13 @@ _ts_decorate([
83
84
  ], CreateUserDto.prototype, "email", void 0);
84
85
  _ts_decorate([
85
86
  (0, _swagger.ApiProperty)({
86
- example: 'password123',
87
- description: 'Password'
87
+ example: 'SecureP@ss123',
88
+ description: 'Password (must meet complexity requirements)'
88
89
  }),
89
90
  (0, _classvalidator.IsString)(),
91
+ (0, _classvalidator.IsNotEmpty)(),
92
+ (0, _passwordvalidator.IsStrongPassword)(),
93
+ (0, _classvalidator.MaxLength)(128),
90
94
  _ts_metadata("design:type", String)
91
95
  ], CreateUserDto.prototype, "password", void 0);
92
96
  _ts_decorate([
@@ -139,6 +143,7 @@ let UpdateUserDto = class UpdateUserDto {
139
143
  _define_property(this, "phone", void 0);
140
144
  _define_property(this, "email", void 0);
141
145
  _define_property(this, "password", void 0);
146
+ _define_property(this, "oldPassword", void 0);
142
147
  _define_property(this, "profilePictureId", void 0);
143
148
  _define_property(this, "isActive", void 0);
144
149
  _define_property(this, "emailVerified", void 0);
@@ -150,7 +155,7 @@ _ts_decorate([
150
155
  (0, _swagger.ApiProperty)({
151
156
  description: 'User ID'
152
157
  }),
153
- (0, _classvalidator.IsString)(),
158
+ (0, _classvalidator.IsUUID)(),
154
159
  _ts_metadata("design:type", String)
155
160
  ], UpdateUserDto.prototype, "id", void 0);
156
161
  _ts_decorate([
@@ -182,12 +187,22 @@ _ts_decorate([
182
187
  ], UpdateUserDto.prototype, "email", void 0);
183
188
  _ts_decorate([
184
189
  (0, _swagger.ApiPropertyOptional)({
185
- description: 'New password'
190
+ description: 'New password (must meet complexity requirements)'
186
191
  }),
187
192
  (0, _classvalidator.IsOptional)(),
188
193
  (0, _classvalidator.IsString)(),
194
+ (0, _passwordvalidator.IsStrongPassword)(),
195
+ (0, _classvalidator.MaxLength)(128),
189
196
  _ts_metadata("design:type", String)
190
197
  ], UpdateUserDto.prototype, "password", void 0);
198
+ _ts_decorate([
199
+ (0, _swagger.ApiPropertyOptional)({
200
+ description: 'Current password (required when changing password on own profile)'
201
+ }),
202
+ (0, _classvalidator.IsOptional)(),
203
+ (0, _classvalidator.IsString)(),
204
+ _ts_metadata("design:type", String)
205
+ ], UpdateUserDto.prototype, "oldPassword", void 0);
191
206
  _ts_decorate([
192
207
  (0, _swagger.ApiPropertyOptional)({
193
208
  description: 'Profile picture file ID'
@@ -44,12 +44,6 @@ function _ts_metadata(k, v) {
44
44
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
45
45
  }
46
46
  let UserCompanyPermission = class UserCompanyPermission {
47
- /* ---------- Helpers ---------- */ isCompanyPermission() {
48
- return this.permissionType === _enums.PermissionType.COMPANY;
49
- }
50
- isBranchPermission() {
51
- return this.permissionType === _enums.PermissionType.BRANCH;
52
- }
53
47
  constructor(){
54
48
  _define_property(this, "id", void 0);
55
49
  /* ---------- Ownership ---------- */ _define_property(this, "userId", void 0);
@@ -8,8 +8,10 @@ Object.defineProperty(exports, "ClearToken", {
8
8
  return ClearToken;
9
9
  }
10
10
  });
11
+ const _utils = require("@flusys/nestjs-shared/utils");
11
12
  const _common = require("@nestjs/common");
12
13
  const _rxjs = require("rxjs");
14
+ const _config = require("../config");
13
15
  const _authconfigservice = require("../services/auth-config.service");
14
16
  function _define_property(obj, key, value) {
15
17
  if (key in obj) {
@@ -38,39 +40,24 @@ function _ts_param(paramIndex, decorator) {
38
40
  decorator(target, key, paramIndex);
39
41
  };
40
42
  }
41
- const DEFAULT_COOKIE_NAME = 'fsn_refresh_token';
42
43
  let ClearToken = class ClearToken {
43
44
  get cookieName() {
44
- return this.authConfig?.getRefreshTokenCookieName() ?? DEFAULT_COOKIE_NAME;
45
+ return this.authConfig?.getRefreshTokenCookieName() ?? _config.DEFAULT_COOKIE_NAME;
45
46
  }
46
47
  intercept(context, next) {
47
48
  const req = context.switchToHttp().getRequest();
48
49
  const res = context.switchToHttp().getResponse();
49
50
  return next.handle().pipe((0, _rxjs.map)((value)=>{
50
- // Clear the refresh token cookie
51
- this.clearRefreshTokenCookie(req, res);
51
+ if ((0, _utils.isBrowserRequest)(req)) {
52
+ res.clearCookie(this.cookieName, {
53
+ httpOnly: true,
54
+ path: '/',
55
+ ...(0, _utils.buildCookieOptions)(req)
56
+ });
57
+ }
52
58
  return value;
53
59
  }));
54
60
  }
55
- /**
56
- * Clear refresh token cookie
57
- */ clearRefreshTokenCookie(req, res) {
58
- const origin = req.headers.origin || '';
59
- const hostname = req.hostname || '';
60
- const isHttps = origin.startsWith('https://') || req.secure;
61
- let cookieDomain = hostname;
62
- const domainParts = hostname.split('.');
63
- if (domainParts.length > 2) {
64
- cookieDomain = '.' + domainParts.slice(-2).join('.');
65
- }
66
- res.clearCookie(this.cookieName, {
67
- httpOnly: true,
68
- secure: isHttps,
69
- sameSite: isHttps ? 'strict' : 'lax',
70
- domain: cookieDomain,
71
- path: '/'
72
- });
73
- }
74
61
  constructor(authConfig){
75
62
  _define_property(this, "authConfig", void 0);
76
63
  this.authConfig = authConfig;
@@ -8,9 +8,11 @@ Object.defineProperty(exports, "SetToken", {
8
8
  return SetToken;
9
9
  }
10
10
  });
11
+ const _utils = require("@flusys/nestjs-shared/utils");
11
12
  const _common = require("@nestjs/common");
12
13
  const _buffer = require("buffer");
13
14
  const _rxjs = require("rxjs");
15
+ const _config = require("../config");
14
16
  const _authconfigservice = require("../services/auth-config.service");
15
17
  function _define_property(obj, key, value) {
16
18
  if (key in obj) {
@@ -39,80 +41,37 @@ function _ts_param(paramIndex, decorator) {
39
41
  decorator(target, key, paramIndex);
40
42
  };
41
43
  }
42
- const DEFAULT_COOKIE_NAME = 'fsn_refresh_token';
43
- const MAX_COOKIE_BYTES = 3500;
44
44
  let SetToken = class SetToken {
45
45
  get cookieName() {
46
- return this.authConfig?.getRefreshTokenCookieName() ?? DEFAULT_COOKIE_NAME;
46
+ return this.authConfig?.getRefreshTokenCookieName() ?? _config.DEFAULT_COOKIE_NAME;
47
+ }
48
+ get maxAgeMs() {
49
+ return (0, _utils.parseDurationToMs)(this.authConfig?.getRefreshTokenExpiration() ?? '7d');
47
50
  }
48
51
  intercept(context, next) {
49
52
  const req = context.switchToHttp().getRequest();
50
53
  const res = context.switchToHttp().getResponse();
51
54
  return next.handle().pipe((0, _rxjs.map)((value)=>{
52
- // Skip if no refreshToken in response
53
- if (!value || !value.refreshToken) {
54
- return value;
55
- }
56
- const isBrowser = this.isBrowserRequest(req);
57
- const tokenValue = value.refreshToken;
58
- if (isBrowser) {
59
- // Browser: Set cookie and remove from response body
60
- this.setRefreshTokenCookie(req, res, tokenValue);
61
- // Return response without refreshToken for browsers
55
+ if (!value?.refreshToken) return value;
56
+ if ((0, _utils.isBrowserRequest)(req)) {
57
+ this.setRefreshTokenCookie(req, res, value.refreshToken);
62
58
  const { refreshToken, ...responseWithoutToken } = value;
63
59
  return responseWithoutToken;
64
60
  }
65
- // API/Mobile: Keep refreshToken in response body
66
61
  return value;
67
62
  }), (0, _rxjs.catchError)((err)=>(0, _rxjs.throwError)(()=>err)));
68
63
  }
69
- /**
70
- * Detect if request is from a browser
71
- * Checks Accept header and custom X-Client-Type header
72
- */ isBrowserRequest(req) {
73
- // Check custom header first (allows explicit client identification)
74
- const clientType = req.headers['x-client-type'];
75
- if (clientType) {
76
- return clientType.toLowerCase() === 'browser' || clientType.toLowerCase() === 'web';
77
- }
78
- // Check Accept header - browsers typically include text/html
79
- const accept = req.headers['accept'] || '';
80
- if (accept.includes('text/html')) {
81
- return true;
82
- }
83
- // Check User-Agent for common browsers
84
- const userAgent = req.headers['user-agent'] || '';
85
- const browserPatterns = /mozilla|chrome|safari|firefox|edge|opera|msie/i;
86
- if (browserPatterns.test(userAgent) && !userAgent.includes('Postman')) {
87
- return true;
88
- }
89
- return false;
90
- }
91
- /**
92
- * Set refresh token in HTTP-only cookie
93
- */ setRefreshTokenCookie(req, res, tokenValue) {
94
- const origin = req.headers.origin || '';
95
- const hostname = req.hostname || '';
96
- const isHttps = origin.startsWith('https://') || req.secure;
97
- let cookieDomain = hostname;
98
- const domainParts = hostname.split('.');
99
- if (domainParts.length > 2) {
100
- cookieDomain = '.' + domainParts.slice(-2).join('.');
101
- }
102
- // Check cookie size
103
- const rawCookieString = `${this.cookieName}=${tokenValue}; HttpOnly; Domain=${cookieDomain}`;
64
+ setRefreshTokenCookie(req, res, tokenValue) {
65
+ const rawCookieString = `${this.cookieName}=${tokenValue}; HttpOnly`;
104
66
  const estimatedBytes = _buffer.Buffer.byteLength(rawCookieString, 'utf8');
105
- if (estimatedBytes > MAX_COOKIE_BYTES) {
67
+ if (estimatedBytes > _config.MAX_COOKIE_BYTES) {
106
68
  throw new _common.PayloadTooLargeException(`Refresh token too large (≈${estimatedBytes} bytes)`);
107
69
  }
108
- // Set HTTP-only secure cookie
109
70
  res.cookie(this.cookieName, tokenValue, {
110
71
  httpOnly: true,
111
- secure: isHttps,
112
- sameSite: isHttps ? 'strict' : 'lax',
113
- domain: cookieDomain,
114
72
  path: '/',
115
- maxAge: 7 * 24 * 60 * 60 * 1000
73
+ maxAge: this.maxAgeMs,
74
+ ...(0, _utils.buildCookieOptions)(req)
116
75
  });
117
76
  }
118
77
  constructor(authConfig){
@@ -123,6 +82,7 @@ let SetToken = class SetToken {
123
82
  SetToken = _ts_decorate([
124
83
  (0, _common.Injectable)(),
125
84
  _ts_param(0, (0, _common.Optional)()),
85
+ _ts_param(0, (0, _common.Inject)(_authconfigservice.AuthConfigService)),
126
86
  _ts_metadata("design:type", Function),
127
87
  _ts_metadata("design:paramtypes", [
128
88
  typeof _authconfigservice.AuthConfigService === "undefined" ? Object : _authconfigservice.AuthConfigService
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Auth Email Provider Interface
2
+ * Auth Email Provider Interface
3
3
  *
4
4
  * This interface defines the contract for email sending in the auth module.
5
5
  * It allows auth to work independently of the email module.