ecrs-auth-core 1.0.102 → 1.0.104

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.
@@ -32,7 +32,7 @@ let AuthController = class AuthController {
32
32
  const additionalData = this.extractClientData(request, userAgent);
33
33
  console.log(`📍 Login attempt from IP: ${clientIp}, User-Agent: ${userAgent}`);
34
34
  // Validate user with IP restriction check
35
- const user = await this.authService.validateUser(body.email, body.password, clientIp);
35
+ const user = await this.authService.validateUser(body.email, body.password, clientIp, Number(body.moduleId));
36
36
  if (!user) {
37
37
  // Save failed login attempt to both tables
38
38
  await this.authService.saveLastLogin({ email: body.email }, clientIp, 'failed', 'Invalid credentials or IP not allowed', additionalData).catch((err) => {
@@ -25,7 +25,7 @@ export declare class AuthService {
25
25
  private readonly employeeWorkProfileRepo;
26
26
  private uploadPhotoDir;
27
27
  constructor(jwtService: JwtService, options: AuthCoreOptions);
28
- validateUser(email: string, password: string, clientIp?: string): Promise<User>;
28
+ validateUser(email: string, password: string, clientIp?: string, moduleId?: number): Promise<User>;
29
29
  /**
30
30
  * Validate IP restriction for a user
31
31
  *
@@ -49,6 +49,7 @@ exports.AuthService = void 0;
49
49
  const common_1 = require("@nestjs/common");
50
50
  const jwt_1 = require("@nestjs/jwt");
51
51
  const bcrypt = __importStar(require("bcrypt"));
52
+ const typeorm_1 = require("typeorm");
52
53
  const constants_1 = require("./constants/constants");
53
54
  let AuthService = class AuthService {
54
55
  constructor(jwtService, options) {
@@ -70,14 +71,41 @@ let AuthService = class AuthService {
70
71
  this.loginDetailsRepo = repositories.loginDetailsRepo || null;
71
72
  this.employeeWorkProfileRepo = repositories.employeeWorkProfileRepo || null;
72
73
  }
73
- async validateUser(email, password, clientIp) {
74
- const user = await this.userRepo.findOne({ where: { email } });
75
- if (!user) {
76
- throw new common_1.UnauthorizedException('Invalid email');
77
- }
78
- const isValid = await bcrypt.compare(password, user.password);
79
- if (!isValid) {
80
- throw new common_1.UnauthorizedException('Invalid password');
74
+ async validateUser(email, password, clientIp, moduleId) {
75
+ // Guard: reject missing or oversized inputs before any DB/bcrypt work.
76
+ // Oversized passwords cause bcrypt to hang (DoS); oversized emails are never valid.
77
+ if (!email || !password || password.length > 72 || email.length > 254) {
78
+ throw new common_1.UnauthorizedException('Invalid credentials');
79
+ }
80
+ // Normalize email for consistent comparison, then use ILike so the DB
81
+ // matches regardless of how the email was originally stored (mixed/upper/lower).
82
+ const normalizedEmail = email.trim().toLowerCase();
83
+ const whereClause = { email: (0, typeorm_1.ILike)(normalizedEmail), deletedBy: null, deletedAt: null, status: 1 };
84
+ //role-id
85
+ //1-"Superadmin" 2-"Admin" 3-"Employee" 5-"CUSTOMER_BOOKER" 6-"SECURITY" 7-"SUPPLIER"
86
+ //module-id
87
+ // 1 "HR" , 2 "ETS" ,3 "Spot",4 "Account",5 "Superadmin",6 "Vendor",7 "Customer"
88
+ const modulearray = [1, 2, 3, 4, 5];
89
+ if (moduleId === 7) {
90
+ whereClause.roleId = (0, typeorm_1.In)([5, 1, 2]);
91
+ }
92
+ else if (moduleId === 6) {
93
+ whereClause.roleId = (0, typeorm_1.In)([7, 1, 2]);
94
+ }
95
+ else if (moduleId !== undefined && modulearray.includes(moduleId)) {
96
+ whereClause.roleId = (0, typeorm_1.In)([1, 2, 3]);
97
+ }
98
+ const user = await this.userRepo.findOne({ where: whereClause });
99
+ // Always run bcrypt.compare regardless of whether the user was found.
100
+ // This prevents timing-based user enumeration: both paths take the same time.
101
+ // A known bcrypt hash is used as a dummy so the operation cost is identical.
102
+ // const DUMMY_HASH = '$2b$10$abcdefghijklmnopqrstuuABCDEFGHIJKLMNOPQRSTUVWXYZ012345';
103
+ // const hashToCompare = user?.password ?? DUMMY_HASH;
104
+ // const isValid = await bcrypt.compare(password, hashToCompare);
105
+ const isValid = user ? await bcrypt.compare(password, user.password) : false;
106
+ // Single generic message — never reveal whether the email exists
107
+ if (!user || !isValid) {
108
+ throw new common_1.UnauthorizedException('Invalid credentials');
81
109
  }
82
110
  if (clientIp && this.ipRestrictionsRepo) {
83
111
  const ipAllowed = await this.validateIpRestriction(user.id, clientIp);
@@ -13,6 +13,7 @@ exports.LoginDto = void 0;
13
13
  // src/dtos/login.dto.ts
14
14
  const swagger_1 = require("@nestjs/swagger");
15
15
  const class_validator_1 = require("class-validator");
16
+ const class_transformer_1 = require("class-transformer");
16
17
  class LoginDto {
17
18
  }
18
19
  exports.LoginDto = LoginDto;
@@ -20,12 +21,17 @@ __decorate([
20
21
  (0, swagger_1.ApiProperty)({ example: 'user@example.com', description: 'User email address used for login' }),
21
22
  (0, class_validator_1.IsEmail)(),
22
23
  (0, class_validator_1.IsNotEmpty)(),
24
+ (0, class_validator_1.MaxLength)(254) // RFC 5321 max; rejects oversized email before DB lookup
25
+ ,
26
+ (0, class_transformer_1.Transform)(({ value }) => typeof value === 'string' ? value.trim() : value),
23
27
  __metadata("design:type", String)
24
28
  ], LoginDto.prototype, "email", void 0);
25
29
  __decorate([
26
30
  (0, swagger_1.ApiProperty)({ example: 'StrongP@ssw0rd', description: 'Plain text password to authenticate' }),
27
31
  (0, class_validator_1.IsString)(),
28
32
  (0, class_validator_1.IsNotEmpty)(),
33
+ (0, class_validator_1.MaxLength)(72) // bcrypt only processes first 72 bytes; anything longer is a DoS attempt
34
+ ,
29
35
  __metadata("design:type", String)
30
36
  ], LoginDto.prototype, "password", void 0);
31
37
  __decorate([
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ecrs-auth-core",
3
- "version": "1.0.102",
3
+ "version": "1.0.104",
4
4
  "description": "Centralized authentication and authorization module for ECRS apps",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",