@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomei/sso",
3
- "version": "0.64.0-staging.1",
3
+ "version": "0.64.0",
4
4
  "description": "Tomei SSO Package",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -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('Invalid credentials.');
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('Invalid credentials.');
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 new Error('Invalid credentials.');
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
- 'Invalid credentials.',
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 isVerified = await speakeasy.totp.verify({
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
- // 4. if not verified, then return false. if verified, Call LoginUser._Repo.update and update user data in database
2013
- if (!isVerified) {
2014
- return false;
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 isVerified = await speakeasy.totp.verify({
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
- // 4. if not verified, then return false. if verified, Call LoginUser._Repo.update and update user data in database
2088
- if (!isVerified) {
2089
- return false;
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 `${this.UserId}:${systemLogin.sessionId}`;
2195
+ return {
2196
+ success: true,
2197
+ sessionId: `${this.UserId}:${systemLogin.sessionId}`,
2198
+ };
2156
2199
  } catch (error) {
2157
2200
  throw error;
2158
2201
  }