ef-keycloak-connect 1.2.4 → 1.3.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": "ef-keycloak-connect",
3
- "version": "1.2.4",
3
+ "version": "1.3.0",
4
4
  "description": "Node JS keycloak adapter for authentication and authorization.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -19,4 +19,4 @@
19
19
  "joi": "^17.6.0",
20
20
  "keycloak-connect": "^10.0.2"
21
21
  }
22
- }
22
+ }
@@ -6,15 +6,18 @@ var memory = new session.MemoryStore();
6
6
  var keycloakConfig = null;
7
7
 
8
8
  const FinesseService = require('./finesseService');
9
+ const TeamsService = require('./teamsService');
10
+
9
11
  const finesseService = new FinesseService();
12
+ const teamsService = new TeamsService();
10
13
 
11
- class KeycloakService extends Keycloak{
14
+ class KeycloakService extends Keycloak {
12
15
 
13
16
  constructor(config) {
14
17
 
15
- keycloakConfig = {...config};
18
+ keycloakConfig = { ...config };
16
19
  super({ store: memory }, keycloakConfig); //initialising keycloak-connect //Keycloak = new Keycloak({store: memory}, config);
17
- // this.keycloakConfig = config;
20
+ // this.keycloakConfig = config;
18
21
  }
19
22
 
20
23
  //Based on the attributes it either authenticate keycloak user or finesse user.
@@ -23,23 +26,23 @@ class KeycloakService extends Keycloak{
23
26
  let token = '';
24
27
 
25
28
  // If finesseUrl is empty it means normal keycloak auth is required.
26
- if(finesseUrl == ''){
29
+ if (finesseUrl == '') {
27
30
 
28
31
  token = await this.getKeycloakTokenWithIntrospect(user_name, user_password, realm_name);
29
32
  return token;
30
33
 
31
- }else{
34
+ } else {
32
35
 
33
36
  // Finesse Auth, takes userRole in argument to create user along with role.
34
37
  token = await this.authenticateFinesse(user_name, user_password, finesseUrl, userRoles, finesseToken)
35
38
  return token;
36
-
39
+
37
40
  }
38
-
41
+
39
42
  }
40
43
 
41
- getAccessToken(user_name, user_password){
42
-
44
+ getAccessToken(user_name, user_password) {
45
+
43
46
  return new Promise(async (resolve, reject) => {
44
47
 
45
48
  var URL = keycloakConfig["auth-server-url"] + 'realms/' + keycloakConfig["realm"] + '/protocol/openid-connect/token';
@@ -74,7 +77,7 @@ class KeycloakService extends Keycloak{
74
77
  }
75
78
 
76
79
  // this function requires an Admin user in keycloak.json having realm-management roles
77
- async getKeycloakTokenWithIntrospect(user_name, user_password, realm_name){
80
+ async getKeycloakTokenWithIntrospect(user_name, user_password, realm_name) {
78
81
 
79
82
  return new Promise(async (resolve, reject) => {
80
83
  let token;
@@ -96,7 +99,7 @@ class KeycloakService extends Keycloak{
96
99
  grant_type: keycloakConfig.GRANT_TYPE,
97
100
  },
98
101
  };
99
- //console.log(config);
102
+
100
103
  try {
101
104
  // T.O.K.E.N R.E.Q.U.E.S.T # 1 ( P.E.R.M.I.S.S.I.O.N.S N.O.T I.N.C.L.U.D.E.D)
102
105
  let tokenResponse = await requestController.httpRequest(config, true);
@@ -116,11 +119,12 @@ class KeycloakService extends Keycloak{
116
119
  config.data.token = token;
117
120
  URL = URL + '/introspect'
118
121
  config.url = URL;
119
- // T.O.K.E.N R.E.Q.U.E.S.T # 3 (A.C.C.E.S.S T.O.K.E.N I.N.T.R.O.S.P.E.C.T.I.O.N)
120
122
 
123
+ // T.O.K.E.N R.E.Q.U.E.S.T # 3 (A.C.C.E.S.S T.O.K.E.N I.N.T.R.O.S.P.E.C.T.I.O.N)
121
124
  try {
122
125
  let intrsopectionResponse = await requestController.httpRequest(config, true);
123
126
  intrsopectionResponse.data.access_token = token;
127
+
124
128
  // T.O.K.E.N R.E.Q.U.E.S.T # 4 ( A.D.M.I.N. T.O.K.E.N)
125
129
  try {
126
130
  config.data.username = keycloakConfig.USERNAME_ADMIN;
@@ -152,16 +156,29 @@ class KeycloakService extends Keycloak{
152
156
  };
153
157
 
154
158
  //Adding user custom attribute to our token object data.
155
- if(getuserDetails.data[0].attributes){
159
+ if (getuserDetails.data[0].attributes) {
156
160
  responseObject.attributes = getuserDetails.data[0].attributes;
157
161
  }
158
162
 
159
- let finalObject = {
160
- 'token': userToken,
161
- 'keycloak_User': responseObject
162
- }
163
- resolve(finalObject);
163
+ delete config.headers.Authorization;
164
+ delete config.data;
164
165
 
166
+ //Fetching Groups data for each user.
167
+ try {
168
+
169
+ let teamData = await this.getUserSupervisedGroups(responseObject.id, responseObject.username);
170
+ responseObject.userTeam = teamData.userTeam;
171
+ responseObject.supervisedTeams = teamData.supervisedTeams;
172
+
173
+ let finalObject = {
174
+ 'token': userToken,
175
+ 'keycloak_User': responseObject
176
+ }
177
+ resolve(finalObject);
178
+
179
+ } catch (error) {
180
+ reject("Error while fetching Groups of User in Auth Process" + error);
181
+ }
165
182
  }
166
183
  catch (error) {
167
184
  reject("Get all users request not sent" + error);
@@ -196,6 +213,48 @@ class KeycloakService extends Keycloak{
196
213
  });
197
214
  }
198
215
 
216
+ async getUserInfoFromToken(username, token) {
217
+
218
+ return new Promise(async (resolve, reject) => {
219
+
220
+ var URL = keycloakConfig["auth-server-url"] + 'realms/' + keycloakConfig.realm + '/protocol/openid-connect/token/introspect';
221
+
222
+ let config = {
223
+ method: 'post',
224
+ url: URL,
225
+ headers: {
226
+ 'Accept': 'application/json',
227
+ 'cache-control': 'no-cache',
228
+ 'Content-Type': 'application/x-www-form-urlencoded'
229
+ },
230
+ data: {
231
+ username: username,
232
+ client_id: keycloakConfig.CLIENT_ID,
233
+ client_secret: keycloakConfig.credentials.secret,
234
+ token: token
235
+ }
236
+ };
237
+
238
+ try {
239
+
240
+ let userInfo = await requestController.httpRequest(config, true);
241
+ if (!(userInfo.data.active)) {
242
+ resolve({
243
+ 'status': 401,
244
+ 'message': 'Provided User Access Token is Expired.'
245
+ });
246
+ }
247
+
248
+ let clientRoles = userInfo.data.resource_access;
249
+ resolve(clientRoles);
250
+
251
+ } catch (error) {
252
+ reject(error);
253
+ }
254
+ });
255
+
256
+ }
257
+
199
258
  createResource(resource_name, resource_scope = keycloakConfig.SCOPE_NAME) {
200
259
  return new Promise(async (resolve, reject) => {
201
260
 
@@ -369,7 +428,7 @@ class KeycloakService extends Keycloak{
369
428
  config.data = JSON.stringify(config.data);
370
429
 
371
430
  try {
372
- let policyResponse = await requestController.httpRequest(config,false);
431
+ let policyResponse = await requestController.httpRequest(config, false);
373
432
  resolve(policyResponse);
374
433
  } catch (error) {
375
434
  reject("Policy error" + error);
@@ -383,7 +442,7 @@ class KeycloakService extends Keycloak{
383
442
 
384
443
  }
385
444
 
386
- createPermission(resourceName, policyName, permissionName, scopeName){
445
+ createPermission(resourceName, policyName, permissionName, scopeName) {
387
446
 
388
447
  return new Promise(async (resolve, reject) => {
389
448
  let token;
@@ -433,7 +492,7 @@ class KeycloakService extends Keycloak{
433
492
  config.data = JSON.stringify(config.data);
434
493
 
435
494
  try {
436
- let policyResponse = await requestController.httpRequest(config,false);
495
+ let policyResponse = await requestController.httpRequest(config, false);
437
496
  resolve(policyResponse);
438
497
  } catch (error) {
439
498
  reject("Policy error" + error);
@@ -503,7 +562,7 @@ class KeycloakService extends Keycloak{
503
562
  });
504
563
  }
505
564
 
506
- revokeUseronResource(resource_name, keycloak_user_id){
565
+ revokeUseronResource(resource_name, keycloak_user_id) {
507
566
  return new Promise(async (resolve, reject) => {
508
567
  let token;
509
568
  try {
@@ -558,6 +617,290 @@ class KeycloakService extends Keycloak{
558
617
  });
559
618
  }
560
619
 
620
+ //function to be used only in teams implementation
621
+ async getUserSupervisedGroups(userId, username) {
622
+
623
+ return new Promise(async (resolve, reject) => {
624
+
625
+ let error;
626
+ let token;
627
+ var URL = keycloakConfig["auth-server-url"] + 'realms/' + keycloakConfig.realm + '/protocol/openid-connect/token';
628
+
629
+ try {
630
+
631
+ var config = {
632
+ method: 'post',
633
+ url: URL,
634
+ headers: {
635
+ 'Accept': 'application/json',
636
+ 'cache-control': 'no-cache',
637
+ 'Content-Type': 'application/x-www-form-urlencoded'
638
+ },
639
+ data: {
640
+ client_id: keycloakConfig.CLIENT_ID,
641
+ username: keycloakConfig.USERNAME_ADMIN,
642
+ password: keycloakConfig.PASSWORD_ADMIN,
643
+ grant_type: keycloakConfig.GRANT_TYPE,
644
+ client_secret: keycloakConfig.credentials.secret
645
+ }
646
+ };
647
+
648
+ try {
649
+
650
+ let adminTokenResponse = await requestController.httpRequest(config, true);
651
+ token = adminTokenResponse.data.access_token;
652
+
653
+ config.method = 'get';
654
+ delete config.data;
655
+ delete config.url;
656
+
657
+ let URL2 = keycloakConfig["auth-server-url"] + 'admin/realms/' + keycloakConfig.realm + '/users/' + userId + '/groups';
658
+ config.url = URL2;
659
+ config.headers.Authorization = 'Bearer ' + token;
660
+
661
+ try {
662
+
663
+ let userGroup = await requestController.httpRequest(config, true);
664
+ let team = {};
665
+
666
+ if (userGroup.data.length != 0) {
667
+
668
+
669
+ let group = userGroup.data;
670
+ let userTeam = {};
671
+ let supervisedTeams = [];
672
+
673
+
674
+ userTeam = {
675
+ 'teamId': group[0].id,
676
+ 'teamName': group[0].name
677
+ }
678
+
679
+ team.userTeam = userTeam;
680
+
681
+ config.method = 'get';
682
+ delete config.data;
683
+ delete config.url;
684
+
685
+ let URL3 = keycloakConfig["auth-server-url"] + 'admin/realms/' + keycloakConfig.realm + '/groups';
686
+ config.url = URL3;
687
+ config.headers.Authorization = 'Bearer ' + token;
688
+
689
+ try {
690
+
691
+ let allGroups = await requestController.httpRequest(config, true);
692
+
693
+ for (let group of allGroups.data) {
694
+
695
+ let result = await teamsService.getGroupByGroupID(group.id, username, token, keycloakConfig);
696
+
697
+ if (result) {
698
+ supervisedTeams.push(result);
699
+ }
700
+ };
701
+
702
+ team.supervisedTeams = supervisedTeams;
703
+ resolve(team);
704
+
705
+ } catch (er) {
706
+
707
+ error = await this.checkErrorType(er);
708
+ reject(error);
709
+ }
710
+ } else {
711
+
712
+ team.userTeam = {};
713
+ team.supervisedTeams = [];
714
+
715
+ resolve(team);
716
+ }
717
+
718
+ } catch (er) {
719
+
720
+ error = await this.checkErrorType(er);
721
+ reject(error);
722
+ }
723
+ } catch (er) {
724
+
725
+ error = await this.checkErrorType(er);
726
+ reject(error);
727
+ }
728
+ } catch (er) {
729
+
730
+ error = await this.checkErrorType(er);
731
+ reject(error);
732
+ };
733
+ });
734
+
735
+ }
736
+
737
+ //function to be used only in teams implementation
738
+ async getTeamUsers(keycloakObj, groupsIdsArr, userToken) {
739
+
740
+ return new Promise(async (resolve, reject) => {
741
+
742
+ let token;
743
+ let message;
744
+ var URL = keycloakConfig["auth-server-url"] + 'realms/' + keycloakConfig.realm + '/protocol/openid-connect/token';
745
+
746
+ try {
747
+
748
+ if (typeof keycloakObj == 'object' && Object.keys(keycloakObj).length != 0
749
+ && Array.isArray(groupsIdsArr) && userToken.length > 0) {
750
+
751
+ //Validate whether user in keycloakObj is same as user in userToken.
752
+ const parseJwt = (userToken) => {
753
+ try {
754
+ return JSON.parse(Buffer.from(userToken.split('.')[1], 'base64').toString());
755
+ } catch (er) {
756
+ return null;
757
+ }
758
+ };
759
+
760
+ let verifyToken = parseJwt(userToken);
761
+
762
+ if (keycloakObj.username != verifyToken.preferred_username) {
763
+
764
+ message = `The data provided in Keycloak Object as an Argument doesn't belong to current Logged-In user.`;
765
+
766
+ resolve({
767
+ "status": 401,
768
+ "message": message
769
+ });
770
+ }
771
+
772
+ var config = {
773
+ method: 'post',
774
+ url: URL,
775
+ headers: {
776
+ 'Accept': 'application/json',
777
+ 'cache-control': 'no-cache',
778
+ 'Content-Type': 'application/x-www-form-urlencoded'
779
+ },
780
+ data: {
781
+ client_id: keycloakConfig.CLIENT_ID,
782
+ username: keycloakConfig.USERNAME_ADMIN,
783
+ password: keycloakConfig.PASSWORD_ADMIN,
784
+ grant_type: keycloakConfig.GRANT_TYPE,
785
+ client_secret: keycloakConfig.credentials.secret
786
+ }
787
+ };
788
+
789
+
790
+ try {
791
+
792
+
793
+ let adminTokenResponse = await requestController.httpRequest(config, true);
794
+ token = adminTokenResponse.data.access_token;
795
+ let allUsers = [];
796
+ let groupsData;
797
+
798
+ config.method = 'get';
799
+ delete config.data;
800
+ delete config.url;
801
+ config.headers.Authorization = 'Bearer ' + token;
802
+ let clientRoles = await this.getUserInfoFromToken(keycloakObj.username, userToken);
803
+
804
+ if (clientRoles.status) {
805
+ resolve(clientRoles);
806
+ }
807
+
808
+ //admin case
809
+ if ('realm-management' in clientRoles) {
810
+
811
+ let URL2 = keycloakConfig["auth-server-url"] + 'admin/realms/' + keycloakConfig.realm + '/groups';
812
+ config.url = URL2;
813
+
814
+ try {
815
+
816
+ let groups = await requestController.httpRequest(config, true);
817
+ delete config.url
818
+
819
+ groupsData = groups.data;
820
+
821
+
822
+ } catch (er) {
823
+
824
+ let error = await this.checkErrorType(er);
825
+ reject(error);
826
+ }
827
+
828
+ } else {
829
+
830
+ //agent case
831
+ if ((keycloakObj.supervisedTeams).length == 0) {
832
+
833
+ resolve([]);
834
+
835
+ //supervisor case
836
+ } else {
837
+
838
+ //if no group ids are provided, send all the users of groups this user supervises.
839
+ if (groupsIdsArr.length == 0) {
840
+
841
+ let supervisedGroups = keycloakObj.supervisedTeams;
842
+ groupsData = supervisedGroups;
843
+
844
+ //only send the users of provided groups.
845
+ } else {
846
+
847
+ let groupsArr = [];
848
+ let idsArr = groupsIdsArr;
849
+
850
+ idsArr.forEach(id => {
851
+ let group = keycloakObj.supervisedTeams.find(group => {
852
+ return group.teamId == id;
853
+ });
854
+
855
+ if (!group) {
856
+
857
+ message = `Given User doesn't suprvise any group against id: ${id}`;
858
+
859
+ resolve({
860
+ "status": 404,
861
+ "message": message
862
+ });
863
+ }
864
+
865
+ groupsArr.push(group);
866
+ });
867
+
868
+ groupsData = groupsArr;
869
+ }
870
+ }
871
+ }
872
+
873
+ allUsers = await teamsService.getUsersOfGroups(groupsData, config, keycloakConfig);
874
+ resolve(allUsers);
875
+
876
+ } catch (er) {
877
+ console.log(er);
878
+ let error = await this.checkErrorType(er);
879
+ console.log(error);
880
+ reject(error);
881
+ }
882
+
883
+
884
+ }
885
+
886
+ message = 'Please pass the valid arguments. First argument must be (should not be empty object,' +
887
+ 'must contain valid key-value pair) and Second argument must be Array of groupIds (could be an empty array)' +
888
+ '3rd Argument must be valid Access Token of current logged-in user.';
889
+
890
+ resolve({
891
+ "status": 400,
892
+ "message": message
893
+ });
894
+
895
+ } catch (er) {
896
+
897
+ let error = await this.checkErrorType(er);
898
+ reject(error);
899
+ };
900
+ });
901
+
902
+ }
903
+
561
904
  // this function requires comma separated list of roles in parameter e.g ["robot","human","customer"];
562
905
  getUsersByRole(keycloak_roles) {
563
906
  return new Promise(async (resolve, reject) => {
@@ -600,30 +943,30 @@ class KeycloakService extends Keycloak{
600
943
 
601
944
  userObject.forEach((user) => {
602
945
 
603
- if(count > 0){
946
+ if (count > 0) {
604
947
 
605
- let userIndex = obj.findIndex(usr => {
948
+ let userIndex = obj.findIndex(usr => {
606
949
  return usr.username == user.username;
607
- });
950
+ });
608
951
 
609
- if(userIndex != -1){
952
+ if (userIndex != -1) {
610
953
  obj[userIndex].roles.push(keycloak_roles[i]);
611
954
  flag = false;
612
- }
955
+ }
613
956
  }
614
-
615
- if(flag == true){
957
+
958
+ if (flag == true) {
616
959
 
617
960
  obj.push({
618
961
  'id': user.id,
619
962
  'username': user.username,
620
- 'firstName': ((user.firstName == undefined)? "" : user.firstName),
621
- 'lastName': ((user.lastName == undefined)? "" : user.lastName),
963
+ 'firstName': ((user.firstName == undefined) ? "" : user.firstName),
964
+ 'lastName': ((user.lastName == undefined) ? "" : user.lastName),
622
965
  'roles': [keycloak_roles[i]]
623
- })
966
+ })
624
967
 
625
968
  }
626
-
969
+
627
970
  flag = true;
628
971
 
629
972
  });
@@ -647,14 +990,14 @@ class KeycloakService extends Keycloak{
647
990
  });
648
991
  }
649
992
 
650
-
651
- async getRealmRoles(adminToken){
993
+
994
+ async getRealmRoles(adminToken) {
652
995
 
653
996
  return new Promise(async (resolve, reject) => {
654
-
997
+
655
998
  let URL = `${keycloakConfig["auth-server-url"]}${keycloakConfig["USERNAME_ADMIN"]}/realms/${keycloakConfig["realm"]}/roles`;
656
999
 
657
-
1000
+
658
1001
 
659
1002
  let config = {
660
1003
  method: 'get',
@@ -680,12 +1023,12 @@ class KeycloakService extends Keycloak{
680
1023
  });
681
1024
  }
682
1025
 
683
-
684
-
685
- async assignRoleToUser(userId, roles, adminToken){
1026
+
1027
+
1028
+ async assignRoleToUser(userId, roles, adminToken) {
686
1029
 
687
1030
  return new Promise(async (resolve, reject) => {
688
-
1031
+
689
1032
  let URL = `${keycloakConfig["auth-server-url"]}${keycloakConfig["USERNAME_ADMIN"]}/realms/${keycloakConfig["realm"]}/users/${userId}/role-mappings/realm`;
690
1033
 
691
1034
  let config = {
@@ -713,14 +1056,14 @@ class KeycloakService extends Keycloak{
713
1056
 
714
1057
  });
715
1058
  }
716
-
717
1059
 
718
- async createUser(username,password,token,userRoles){
1060
+
1061
+ async createUser(username, password, token, userRoles) {
719
1062
 
720
1063
  let assignRole = [];
721
1064
 
722
1065
  return new Promise(async (resolve, reject) => {
723
-
1066
+
724
1067
  let URL = `${keycloakConfig["auth-server-url"]}${keycloakConfig["USERNAME_ADMIN"]}/realms/${keycloakConfig["realm"]}/users`;
725
1068
 
726
1069
  let data = {
@@ -735,7 +1078,7 @@ class KeycloakService extends Keycloak{
735
1078
  ]
736
1079
  }
737
1080
 
738
-
1081
+
739
1082
 
740
1083
  let config = {
741
1084
  method: 'post',
@@ -751,22 +1094,22 @@ class KeycloakService extends Keycloak{
751
1094
 
752
1095
  let tokenResponse = await requestController.httpRequest(config, false);
753
1096
 
754
- if(userRoles != []){
1097
+ if (userRoles != []) {
755
1098
  //Get the user id at time of creation
756
1099
  let userLocation = tokenResponse.headers.location;
757
1100
  let userLocationSplit = userLocation.split("/");
758
1101
  let userId = userLocationSplit[(userLocationSplit.length) - 1];
759
1102
 
760
-
1103
+
761
1104
  //Get list of all the roles in keycloak realm
762
1105
  let realmRoles = await this.getRealmRoles(token);
763
-
1106
+
764
1107
  //checking whether role exist in realmRoles object array:
765
- for(let role of realmRoles.data){
766
-
1108
+ for (let role of realmRoles.data) {
1109
+
767
1110
  userRoles.forEach(userRole => {
768
1111
 
769
- if(role.name == userRole.toLocaleLowerCase()){
1112
+ if (role.name == userRole.toLocaleLowerCase()) {
770
1113
  assignRole.push({
771
1114
  id: role.id,
772
1115
  name: role.name
@@ -780,16 +1123,16 @@ class KeycloakService extends Keycloak{
780
1123
  let roleAssigned = await this.assignRoleToUser(userId, assignRole, token);
781
1124
 
782
1125
  //Role assigned with status
783
- if(roleAssigned.status == 204){
1126
+ if (roleAssigned.status == 204) {
784
1127
  resolve(tokenResponse);
785
1128
  }
786
1129
 
787
- }else{
1130
+ } else {
788
1131
 
789
1132
  resolve(tokenResponse);
790
1133
 
791
1134
  }
792
-
1135
+
793
1136
 
794
1137
  }
795
1138
  catch (err) {
@@ -803,132 +1146,150 @@ class KeycloakService extends Keycloak{
803
1146
  }
804
1147
 
805
1148
  //Authenticating Finesse User
806
- async authenticateFinesse(username,password, finesseUrl, userRoles, finesseToken){
807
-
1149
+ async authenticateFinesse(username, password, finesseUrl, userRoles, finesseToken) {
1150
+
808
1151
  //Authentication of Finesse User, it returns a status code 200 if user found and 401 if unauthorized.
809
1152
  let finesseLoginResponse;
810
1153
 
811
- if(finesseToken.length == 0){
812
- finesseLoginResponse = await finesseService.authenticateUserViaFinesse(username,password,finesseUrl);
1154
+ if (finesseToken.length == 0) {
1155
+ finesseLoginResponse = await finesseService.authenticateUserViaFinesse(username, password, finesseUrl);
813
1156
 
814
- }else{
815
- finesseLoginResponse = await finesseService.authenticateUserViaFinesseSSO(username,finesseToken,finesseUrl);
1157
+ } else {
1158
+ finesseLoginResponse = await finesseService.authenticateUserViaFinesseSSO(username, finesseToken, finesseUrl);
816
1159
  }
817
1160
 
818
1161
  //If user is SSO then password is not provided, we are setting up a pre-defined password.
819
- password = (password.length == 0)?"123456":password;
820
-
1162
+ password = (password.length == 0) ? "123456" : password;
1163
+
821
1164
  let authenticatedByKeycloak = false;
822
1165
  let keycloakAuthToken = null;
823
1166
  let timeoutErr = null;
824
1167
 
825
- if(finesseLoginResponse.status == 200){
826
- try{
827
-
1168
+ if (finesseLoginResponse.status == 200) {
1169
+ try {
1170
+
828
1171
  //Checking whether finesse user already exist in keycloak and fetch its token
829
- keycloakAuthToken = await this.getKeycloakTokenWithIntrospect(username,password,keycloakConfig["realm"]);
1172
+ keycloakAuthToken = await this.getKeycloakTokenWithIntrospect(username, password, keycloakConfig["realm"]);
830
1173
  authenticatedByKeycloak = true;
831
-
832
- }catch(err){
833
1174
 
834
- if(err.response.status == 401){
1175
+ } catch (err) {
1176
+
1177
+ if (err.response.status == 401) {
835
1178
 
836
1179
  console.log("User doesn't exist in Keycloak, syncing finesse user in keycloak...");
837
1180
 
838
- }else{
1181
+ } else {
839
1182
 
840
- throw({
1183
+ throw ({
841
1184
  "status": err.response.status,
842
1185
  "message": err.response.data.error_description
843
1186
  });
844
1187
 
845
1188
  }
846
1189
 
847
- }finally{
848
-
849
- //Finesse User not found in keycloak, so we are going to create one.
850
- if(!authenticatedByKeycloak){
1190
+ } finally {
851
1191
 
852
- try{
1192
+ //Finesse User not found in keycloak, so we are going to create one.
1193
+ if (!authenticatedByKeycloak) {
853
1194
 
854
- //Fetching admin token, we pass it in our "Create User" API for authorization
855
- keycloakAuthToken = await this.getKeycloakTokenWithIntrospect(keycloakConfig["USERNAME_ADMIN"],keycloakConfig["PASSWORD_ADMIN"],keycloakConfig["realm"]);
856
- }catch(err){
1195
+ try {
857
1196
 
858
- if(err.code == "ETIMEDOUT"){
1197
+ //Fetching admin token, we pass it in our "Create User" API for authorization
1198
+ keycloakAuthToken = await this.getKeycloakTokenWithIntrospect(keycloakConfig["USERNAME_ADMIN"], keycloakConfig["PASSWORD_ADMIN"], keycloakConfig["realm"]);
1199
+ } catch (err) {
859
1200
 
860
- throw({
861
- 'Keycloak login status': 408,
862
- 'keycloak login message': `Keycloak server unaccessable against URL: ${keycloakConfig["auth-server-url"]}`
863
- });
1201
+ if (err.code == "ETIMEDOUT") {
864
1202
 
865
- }else{
866
- throw({
867
- "status": err.response.status,
868
- "message": "Error While getting Keycloak admin token: "+ err.response.data.error_description
869
- });
870
- }
1203
+ throw ({
1204
+ 'Keycloak login status': 408,
1205
+ 'keycloak login message': `Keycloak server unaccessable against URL: ${keycloakConfig["auth-server-url"]}`
1206
+ });
871
1207
 
1208
+ } else {
1209
+ throw ({
1210
+ "status": err.response.status,
1211
+ "message": "Error While getting Keycloak admin token: " + err.response.data.error_description
1212
+ });
872
1213
  }
873
1214
 
874
- if(keycloakAuthToken.token){
1215
+ }
1216
+
1217
+ if (keycloakAuthToken.token) {
875
1218
 
876
- let token = keycloakAuthToken.token;
1219
+ let token = keycloakAuthToken.token;
877
1220
 
878
- //validating customer Before Creation
879
- let {error, value} = validateUser({username, password, token, userRoles});
1221
+ //validating customer Before Creation
1222
+ let { error, value } = validateUser({ username, password, token, userRoles });
880
1223
 
881
- if(error){
1224
+ if (error) {
882
1225
 
883
- throw({
884
- "status": 400,
885
- "message": "Error while creation of user, error message: "+ error.details[0].message
886
- })
887
- }
1226
+ throw ({
1227
+ "status": 400,
1228
+ "message": "Error while creation of user, error message: " + error.details[0].message
1229
+ })
888
1230
  }
1231
+ }
889
1232
 
890
- try{
891
- //Creating Finesse User inside keycloak.
892
- let userCreated = await this.createUser(username,password,keycloakAuthToken.token,userRoles);
893
-
894
- if(userCreated.status == 201){
1233
+ try {
1234
+ //Creating Finesse User inside keycloak.
1235
+ let userCreated = await this.createUser(username, password, keycloakAuthToken.token, userRoles);
895
1236
 
896
- //Returning the token of recently created User
897
- keycloakAuthToken = await this.getKeycloakTokenWithIntrospect(username,password,keycloakConfig["realm"]);
898
- }
899
-
1237
+ if (userCreated.status == 201) {
900
1238
 
901
- }catch(err){
1239
+ //Returning the token of recently created User
1240
+ keycloakAuthToken = await this.getKeycloakTokenWithIntrospect(username, password, keycloakConfig["realm"]);
1241
+ }
902
1242
 
903
- if(err.code == "ETIMEDOUT"){
904
1243
 
905
- throw({
906
- 'Keycloak login status': 408,
907
- 'keycloak login message': `Keycloak server unaccessable against URL: ${keycloakConfig["auth-server-url"]}`
908
- });
1244
+ } catch (err) {
909
1245
 
910
- }else{
1246
+ if (err.code == "ETIMEDOUT") {
911
1247
 
912
- console.log(err);
1248
+ throw ({
1249
+ 'Keycloak login status': 408,
1250
+ 'keycloak login message': `Keycloak server unaccessable against URL: ${keycloakConfig["auth-server-url"]}`
1251
+ });
913
1252
 
914
- throw({
915
- "status": err.response.status,
916
- "message": "Error While creating Keycloak user: "+ err.response.data.error_description
917
- });
918
- }
1253
+ } else {
1254
+
1255
+ console.log(err);
1256
+
1257
+ throw ({
1258
+ "status": err.response.status,
1259
+ "message": "Error While creating Keycloak user: " + err.response.data.error_description
1260
+ });
1261
+ }
919
1262
  }
920
1263
  }
921
1264
  }
922
-
1265
+
923
1266
  return keycloakAuthToken;
924
1267
 
925
- }else{
1268
+ } else {
926
1269
 
927
1270
  return finesseLoginResponse
928
1271
 
929
1272
  }
930
1273
  }
931
1274
 
1275
+ async checkErrorType(err) {
1276
+
1277
+ if (err.code == "ETIMEDOUT") {
1278
+
1279
+ return ({
1280
+ 'Keycloak login status': 408,
1281
+ 'keycloak login message': `Keycloak server unaccessable against URL: ${keycloakConfig["auth-server-url"]}`
1282
+ });
1283
+
1284
+ } else {
1285
+
1286
+ return ({
1287
+ "status": err.response.status,
1288
+ "message": "Error: " + err.response.data.error_description
1289
+ });
1290
+ }
1291
+ }
1292
+
932
1293
  }
933
1294
 
934
1295
  function validateUser(userData) {
@@ -938,7 +1299,7 @@ function validateUser(userData) {
938
1299
  token: Joi.string().required(),
939
1300
  userRoles: Joi.array().items(Joi.string()).allow(null)
940
1301
  });
941
-
1302
+
942
1303
  return schema.validate(userData);
943
1304
  }
944
1305
 
@@ -0,0 +1,141 @@
1
+ let requestController = require("../controller/requestController.js");
2
+
3
+ class TeamsService {
4
+
5
+ constructor() {
6
+
7
+ }
8
+
9
+ //This function is being used inside getUserSupervisedGroups()
10
+ async getGroupByGroupID(groupId, username, token, keycloakConfig) {
11
+
12
+ return new Promise(async (resolve, reject) => {
13
+
14
+ try {
15
+
16
+ let URL = keycloakConfig["auth-server-url"] + 'admin/realms/' + keycloakConfig.realm + '/groups/' + groupId + '/';
17
+
18
+ var config = {
19
+ method: 'get',
20
+ url: URL,
21
+ headers: {
22
+ 'Accept': 'application/json',
23
+ 'cache-control': 'no-cache',
24
+ 'Content-Type': 'application/x-www-form-urlencoded'
25
+ },
26
+ headers: {
27
+ 'Authorization': 'Bearer ' + token
28
+ }
29
+ };
30
+
31
+ try {
32
+
33
+ let groupAttributes = await requestController.httpRequest(config, false);
34
+ let attributes = groupAttributes.data.attributes;
35
+
36
+ if (attributes != null) {
37
+
38
+ if ('supervisor' in attributes) {
39
+
40
+ let supervisors = attributes['supervisor'][0].split(",");
41
+
42
+ if (supervisors.includes(username)) {
43
+
44
+ resolve({
45
+ 'teamId': groupAttributes.data.id,
46
+ 'teamName': groupAttributes.data.name
47
+ });
48
+ }
49
+ }
50
+ }
51
+
52
+ resolve(null);
53
+
54
+ } catch (error) {
55
+ reject(error);
56
+ }
57
+ } catch (er) {
58
+ reject("error" + er);
59
+ };
60
+ });
61
+ }
62
+
63
+ //this function is being used inside getTeamUsers()
64
+ async getUsersOfGroups(groups, config, keycloakConfig) {
65
+
66
+ return new Promise(async (resolve, reject) => {
67
+
68
+ try {
69
+ let allUsers = [];
70
+ let rolesArr = [];
71
+
72
+ if (groups.length > 0) {
73
+
74
+ for (let group of groups) {
75
+
76
+ let id = null;
77
+ let name = null;
78
+
79
+ if (typeof group === 'object') {
80
+ id = (group.id) ? group.id : group.teamId;
81
+ name = (group.name) ? group.name : group.teamName;
82
+ }
83
+
84
+ let URL = keycloakConfig["auth-server-url"] + 'admin/realms/' + keycloakConfig.realm + '/groups/' + id + '/members';
85
+ config.url = URL;
86
+ let users = await requestController.httpRequest(config, true);
87
+
88
+ if (users.data.length > 0) {
89
+
90
+ for (let user of users.data) {
91
+
92
+ try {
93
+
94
+ let URL2 = keycloakConfig["auth-server-url"] + 'admin/realms/' + keycloakConfig.realm + '/users/' + user.id + '/role-mappings';
95
+ config.url = URL2;
96
+ let rolesObj = await requestController.httpRequest(config, true);
97
+
98
+ rolesArr = rolesObj.data.realmMappings.map(roles => {
99
+ return roles.name;
100
+ });
101
+
102
+ } catch (er) {
103
+ reject(er);
104
+ }
105
+
106
+ let isExist = (allUsers).find(x => x.username == user.username);
107
+
108
+ if (!isExist) {
109
+ allUsers.push({
110
+ 'id': user.id,
111
+ 'username': user.username,
112
+ 'firstName': (user.firstName) ? user.firstName : '',
113
+ 'lastName': (user.lastName) ? user.lastName : '',
114
+ 'realm': keycloakConfig.realm,
115
+ 'roles': rolesArr,
116
+ 'team': {
117
+ 'teamId': id,
118
+ 'teamName': name
119
+ }
120
+ });
121
+ }
122
+
123
+ }
124
+
125
+ }
126
+
127
+ }
128
+
129
+ resolve(allUsers);
130
+ }
131
+
132
+ resolve([]);
133
+
134
+ } catch (er) {
135
+ reject(er);
136
+ }
137
+ });
138
+ }
139
+ }
140
+
141
+ module.exports = TeamsService;