@tomei/sso 0.64.0-staging.1 → 0.64.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.
- package/.husky/commit-msg +6 -0
- package/dist/src/components/login-user/user.d.ts +22 -3
- package/dist/src/components/login-user/user.js +60 -15
- package/dist/src/components/login-user/user.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/sonar-project.properties +23 -0
- package/src/components/login-user/user.ts +60 -17
package/package.json
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
sonar.projectKey=all-tomei-projects_sso
|
2
|
+
sonar.organization=all-tomei-projects
|
3
|
+
sonar.exclusions=**/*.js,test-data,dist,coverage, node_modules, __tests__, **/*.spec.ts, __mocks__
|
4
|
+
sonar.scm.provider=git
|
5
|
+
|
6
|
+
sonar.sources=src
|
7
|
+
sonar.test=__tests__
|
8
|
+
sonar.test.inclusions=src/**/*.spec.ts
|
9
|
+
|
10
|
+
sonar.javascript.lcov.reportPaths=./coverage/lcov.info
|
11
|
+
sonar.testExecutionReportPaths=coverage/test-report.xml
|
12
|
+
sonar.sourceEnconding=UTF-8
|
13
|
+
|
14
|
+
# This is the name and version displayed in the SonarCloud UI.
|
15
|
+
#sonar.projectName=sso
|
16
|
+
#sonar.projectVersion=1.0
|
17
|
+
|
18
|
+
|
19
|
+
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
|
20
|
+
#sonar.sources=.
|
21
|
+
|
22
|
+
# Encoding of the source code. Default is default system encoding
|
23
|
+
#sonar.sourceEncoding=UTF-8
|
@@ -560,11 +560,13 @@ export class User extends UserBase {
|
|
560
560
|
this.UpdatedAt = userAttr.UpdatedAt;
|
561
561
|
this.staffs = userAttr.staffs;
|
562
562
|
} else {
|
563
|
+
console.error('User not found for email:', email);
|
563
564
|
throw new ClassError('User', 'UserErrMsg0X', 'Invalid Credentials');
|
564
565
|
}
|
565
566
|
}
|
566
567
|
|
567
568
|
if (this.ObjectId && this.Email !== email) {
|
569
|
+
console.error('Email mismatch:', this.Email, email);
|
568
570
|
throw new Error('Invalid credentials.');
|
569
571
|
}
|
570
572
|
|
@@ -585,7 +587,7 @@ export class User extends UserBase {
|
|
585
587
|
},
|
586
588
|
});
|
587
589
|
if (!system) {
|
588
|
-
throw new Error('
|
590
|
+
throw new Error('Access denied: invalid or unauthorized system.');
|
589
591
|
}
|
590
592
|
|
591
593
|
// 1.5: Instantiate new PasswordHashService object and call PasswordHashService.verify method to check whether the param.Password is correct.
|
@@ -596,6 +598,7 @@ export class User extends UserBase {
|
|
596
598
|
this.Password,
|
597
599
|
);
|
598
600
|
if (!isPasswordValid) {
|
601
|
+
console.error('Invalid password for user:', this.UserId);
|
599
602
|
throw new Error('Invalid credentials.');
|
600
603
|
}
|
601
604
|
|
@@ -614,12 +617,14 @@ export class User extends UserBase {
|
|
614
617
|
await User.releaseLock(this.UserId, dbTransaction);
|
615
618
|
this.Status = UserStatus.ACTIVE;
|
616
619
|
} else {
|
617
|
-
throw new Error(
|
620
|
+
throw new Error(
|
621
|
+
'Your account has been locked. Please contact the administrator for assistance.',
|
622
|
+
);
|
618
623
|
}
|
619
624
|
}
|
620
625
|
} catch (error) {
|
621
626
|
await this.incrementFailedLoginAttemptCount(dbTransaction);
|
622
|
-
throw
|
627
|
+
throw error;
|
623
628
|
}
|
624
629
|
|
625
630
|
// 2.1: Call alertNewLogin to check whether the ip used is new ip and alert the user if it's new.
|
@@ -674,6 +679,7 @@ export class User extends UserBase {
|
|
674
679
|
ApplicationConfig.getComponentConfigValue('sessionName');
|
675
680
|
|
676
681
|
if (!sessionName) {
|
682
|
+
console.error('Session name is not set in the configuration');
|
677
683
|
throw new Error('Session name is not set in the configuration');
|
678
684
|
}
|
679
685
|
|
@@ -765,6 +771,7 @@ export class User extends UserBase {
|
|
765
771
|
},
|
766
772
|
);
|
767
773
|
}
|
774
|
+
console.error('Login failed:', error);
|
768
775
|
throw error;
|
769
776
|
}
|
770
777
|
}
|
@@ -803,7 +810,7 @@ export class User extends UserBase {
|
|
803
810
|
dbTransaction,
|
804
811
|
});
|
805
812
|
|
806
|
-
for (const usergroup of userGroups) {
|
813
|
+
outer: for (const usergroup of userGroups) {
|
807
814
|
const group = usergroup.Group;
|
808
815
|
const groupSystemAccess = await User.getInheritedSystemAccess(
|
809
816
|
dbTransaction,
|
@@ -813,7 +820,7 @@ export class User extends UserBase {
|
|
813
820
|
for (const system of groupSystemAccess) {
|
814
821
|
if (system.SystemCode === systemCode) {
|
815
822
|
isUserHaveAccess = true;
|
816
|
-
break;
|
823
|
+
break outer;
|
817
824
|
}
|
818
825
|
}
|
819
826
|
}
|
@@ -823,6 +830,7 @@ export class User extends UserBase {
|
|
823
830
|
throw new Error("User don't have access to the system.");
|
824
831
|
}
|
825
832
|
} catch (error) {
|
833
|
+
console.error('Error checking system access:', error);
|
826
834
|
throw error;
|
827
835
|
}
|
828
836
|
}
|
@@ -1732,7 +1740,7 @@ export class User extends UserBase {
|
|
1732
1740
|
throw new ClassError(
|
1733
1741
|
'LoginUser',
|
1734
1742
|
'LoginUserErrMsg0X',
|
1735
|
-
'
|
1743
|
+
'Your account has been locked due to too many failed login attempts, please contact IT Support for instructions on how to unlock your account.',
|
1736
1744
|
);
|
1737
1745
|
}
|
1738
1746
|
}
|
@@ -2003,15 +2011,31 @@ export class User extends UserBase {
|
|
2003
2011
|
}
|
2004
2012
|
|
2005
2013
|
// 3. Verify the mfaToken by calling speakeasy.totp.verify
|
2006
|
-
const
|
2014
|
+
const isCurrentValid = await speakeasy.totp.verify({
|
2007
2015
|
secret: userMFAConfig.totp.secret,
|
2008
2016
|
encoding: 'base32',
|
2009
2017
|
token: mfaToken,
|
2018
|
+
window: 0, // strict current time window
|
2010
2019
|
});
|
2020
|
+
if (!isCurrentValid) {
|
2021
|
+
const isExpired = await speakeasy.totp.verify({
|
2022
|
+
secret: userMFAConfig.totp.secret,
|
2023
|
+
encoding: 'base32',
|
2024
|
+
token: mfaToken,
|
2025
|
+
window: 2, // allow slight leeway: previous or next 2 time steps
|
2026
|
+
});
|
2011
2027
|
|
2012
|
-
|
2013
|
-
|
2014
|
-
|
2028
|
+
if (isExpired) {
|
2029
|
+
return {
|
2030
|
+
success: false,
|
2031
|
+
reason: 'MFA token has expired. Please try again.',
|
2032
|
+
};
|
2033
|
+
} else {
|
2034
|
+
return {
|
2035
|
+
success: false,
|
2036
|
+
reason: 'Invalid MFA token. Check your authenticator app.',
|
2037
|
+
};
|
2038
|
+
}
|
2015
2039
|
}
|
2016
2040
|
|
2017
2041
|
user.MFAEnabled = 1;
|
@@ -2040,7 +2064,7 @@ export class User extends UserBase {
|
|
2040
2064
|
const systemLogin = userSession.systemLogins.find(
|
2041
2065
|
(e) => e.code === systemCode,
|
2042
2066
|
);
|
2043
|
-
return `${userId}:${systemLogin.sessionId}
|
2067
|
+
return { success: true, sessionId: `${userId}:${systemLogin.sessionId}` };
|
2044
2068
|
}
|
2045
2069
|
|
2046
2070
|
// This method will verify 2FA codes
|
@@ -2078,15 +2102,31 @@ export class User extends UserBase {
|
|
2078
2102
|
}
|
2079
2103
|
|
2080
2104
|
// 3. Verify the mfaToken by calling speakeasy.totp.verify
|
2081
|
-
const
|
2105
|
+
const isCurrentValid = await speakeasy.totp.verify({
|
2082
2106
|
secret: userMFAConfig.totp.secret,
|
2083
2107
|
encoding: 'base32',
|
2084
2108
|
token: mfaToken,
|
2109
|
+
window: 0, // strict current time window
|
2085
2110
|
});
|
2111
|
+
if (!isCurrentValid) {
|
2112
|
+
const isExpired = await speakeasy.totp.verify({
|
2113
|
+
secret: userMFAConfig.totp.secret,
|
2114
|
+
encoding: 'base32',
|
2115
|
+
token: mfaToken,
|
2116
|
+
window: 2, // allow slight leeway: previous or next 2 time steps
|
2117
|
+
});
|
2086
2118
|
|
2087
|
-
|
2088
|
-
|
2089
|
-
|
2119
|
+
if (isExpired) {
|
2120
|
+
return {
|
2121
|
+
success: false,
|
2122
|
+
reason: 'MFA token has expired. Please try again.',
|
2123
|
+
};
|
2124
|
+
} else {
|
2125
|
+
return {
|
2126
|
+
success: false,
|
2127
|
+
reason: 'Invalid MFA token. Check your authenticator app.',
|
2128
|
+
};
|
2129
|
+
}
|
2090
2130
|
}
|
2091
2131
|
|
2092
2132
|
// 5. Retrieve Session
|
@@ -2109,7 +2149,7 @@ export class User extends UserBase {
|
|
2109
2149
|
const systemLogin = userSession.systemLogins.find(
|
2110
2150
|
(e) => e.code === systemCode,
|
2111
2151
|
);
|
2112
|
-
return `${userId}:${systemLogin.sessionId}
|
2152
|
+
return { success: true, sessionId: `${userId}:${systemLogin.sessionId}` };
|
2113
2153
|
}
|
2114
2154
|
|
2115
2155
|
public async bypass2FA(systemCode: string, dbTransaction: any) {
|
@@ -2152,7 +2192,10 @@ export class User extends UserBase {
|
|
2152
2192
|
const systemLogin = userSession.systemLogins.find(
|
2153
2193
|
(e) => e.code === systemCode,
|
2154
2194
|
);
|
2155
|
-
return
|
2195
|
+
return {
|
2196
|
+
success: true,
|
2197
|
+
sessionId: `${this.UserId}:${systemLogin.sessionId}`,
|
2198
|
+
};
|
2156
2199
|
} catch (error) {
|
2157
2200
|
throw error;
|
2158
2201
|
}
|