ecrs-auth-core 1.0.103 → 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.
- package/dist/auth.service.js +19 -9
- package/dist/dtos/login.dto.js +6 -0
- package/package.json +1 -1
package/dist/auth.service.js
CHANGED
|
@@ -72,30 +72,40 @@ let AuthService = class AuthService {
|
|
|
72
72
|
this.employeeWorkProfileRepo = repositories.employeeWorkProfileRepo || null;
|
|
73
73
|
}
|
|
74
74
|
async validateUser(email, password, clientIp, moduleId) {
|
|
75
|
-
|
|
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 };
|
|
76
84
|
//role-id
|
|
77
85
|
//1-"Superadmin" 2-"Admin" 3-"Employee" 5-"CUSTOMER_BOOKER" 6-"SECURITY" 7-"SUPPLIER"
|
|
78
86
|
//module-id
|
|
79
87
|
// 1 "HR" , 2 "ETS" ,3 "Spot",4 "Account",5 "Superadmin",6 "Vendor",7 "Customer"
|
|
80
88
|
const modulearray = [1, 2, 3, 4, 5];
|
|
81
89
|
if (moduleId === 7) {
|
|
82
|
-
// Customer module: allow CUSTOMER_BOOKER(5), SECURITY(6), SUPPLIER(7)
|
|
83
90
|
whereClause.roleId = (0, typeorm_1.In)([5, 1, 2]);
|
|
84
91
|
}
|
|
85
92
|
else if (moduleId === 6) {
|
|
86
|
-
// vendor module: allow CUSTOMER_BOOKER(5), SECURITY(6), SUPPLIER(7)
|
|
87
93
|
whereClause.roleId = (0, typeorm_1.In)([7, 1, 2]);
|
|
88
94
|
}
|
|
89
95
|
else if (moduleId !== undefined && modulearray.includes(moduleId)) {
|
|
90
96
|
whereClause.roleId = (0, typeorm_1.In)([1, 2, 3]);
|
|
91
97
|
}
|
|
92
98
|
const user = await this.userRepo.findOne({ where: whereClause });
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
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');
|
|
99
109
|
}
|
|
100
110
|
if (clientIp && this.ipRestrictionsRepo) {
|
|
101
111
|
const ipAllowed = await this.validateIpRestriction(user.id, clientIp);
|
package/dist/dtos/login.dto.js
CHANGED
|
@@ -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([
|