ef-keycloak-connect 1.3.0 → 1.3.2

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/README.md CHANGED
@@ -332,5 +332,31 @@ It takes 5 arguments:
332
332
  ##### Example of non SSO Finesse Auth:
333
333
 
334
334
  authenticateFinesse('johndoe', '12345', `https://${finesse_server_url}:${port}`, ['agent','supervisor'], '')
335
+
336
+ ### generateAccessTokenFromRefreshToken(refreshToken)
337
+
338
+ This function generates a new access_token by using the refreshToken received in parameter.
339
+
340
+ It takes a signle argument:
341
+
342
+ - refreshToken: Refresh Token is used to generate the new access token.
343
+
344
+ Response:
345
+
346
+ - If the refresh token is valid then a new access token is returned in reponse along with status code 200.
347
+
348
+ ```
349
+ {
350
+ "status": 200,
351
+ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJqeEMzZDV5VVZRS1ktY3MwSmhQd29DVzllNjB0VkFPQXBIUDlWUlhsejdBIn0.eyJleHAiOjE2NzgyNzIzNDEsImlhdCI6MTY3ODI3MjEwNSwianRpIjoiNWVkMDBiYzgtNDM1MC00MjQ2LTllOTEtYjE4ZGIyMzc5YTI2IiwiaXNzIjoiaHR0cDovLzE5Mi4xNjguMS4yMDQ6ODA4MC9hdXRoL3JlYWxtcy9EZW1vLUtleWNsb2FrLVJlYWxtIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6IjY5OGRkYWFkLTZkZTYtNDY1YS04Mjg1LTQ4MWI5NjZjMmYxNiIsInR5cCI6IkJlYXJlciIsImF6cCI6ImRlbW8ta2V5Y2xvYWstY2xpZW50Iiwic2Vzc2lvbl9zdGF0ZSI6ImM2NTNmNDk5LWJlNzMtNDIyNS05MGU4LThkYjBjNDkwYTc5MCIsImFjciI6IjEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGVmYXVsdC1yb2xlcy1kZW1vLWtleWNsb2FrLXJlYWxtIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiIsImFnZW50LXJvbGUiXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJhdXRob3JpemF0aW9uIjp7InBlcm1pc3Npb25zIjpbeyJyc2lkIjoiNDBhNzg1MjYtNjNiNy00NDcwLThkZWEtZjRlZDViNTUwOTUzIiwicnNuYW1lIjoiRGVmYXVsdCBSZXNvdXJjZSJ9XX0sInNjb3BlIjoiZW1haWwgcHJvZmlsZSIsInNpZCI6ImM2NTNmNDk5LWJlNzMtNDIyNS05MGU4LThkYjBjNDkwYTc5MCIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6InphcnlhYiByYXphIiwiYWdlbnRFeHRlbnNpb24iOiI4MDgxLDYwMDEiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ6YXJ5YWIgcmF6YSIsImdpdmVuX25hbWUiOiJ6YXJ5YWIiLCJmYW1pbHlfbmFtZSI6InJhemEiLCJlbWFpbCI6InphcnlhYkBlbWFpbC5jb20ifQ.Y8NVa0OzAPBwtb6cGyhZxMEyv-o_nTA9ZcvXNcmcEMivqTT0dTE95yNKXYxUQuhTAWE6mPJDwuZ0GuEco7hhxQ6IjjH2j0QwjvqEFFi7KNNdIi-yS4q0elNCjxar8zkHY3Gy8a2d7C_9CQuBN-ernV-JYcmGHENlpmJJpyHfZ5aNkzrcHN5b9qDx2-YZm8pkgFuUv8bwogFFeECzclOlrSGHmaiOI1gp2jkUIw8q23LB8YvzdVg5aHgSDcTKD4gXRrG7C_OQRbCmycOtW4iECLlURnlbbF5Rq4vxzrHjRtBAQmVZ86ITP7yDqEPOWfIxHjODDWWHNL2r7dK8OhNK_g"
352
+ }
353
+
354
+ - If the refresh token is invalid then an error message is returned in reponse along with status code 400.
355
+
356
+ ```
357
+ {
358
+ "status": 400,
359
+ "message": "Refresh Token expired, please login again"
360
+ }
335
361
 
336
362
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ef-keycloak-connect",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Node JS keycloak adapter for authentication and authorization.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -81,6 +81,7 @@ class KeycloakService extends Keycloak {
81
81
 
82
82
  return new Promise(async (resolve, reject) => {
83
83
  let token;
84
+ let refresh_token;
84
85
  var URL = keycloakConfig["auth-server-url"] + 'realms/' + realm_name + '/protocol/openid-connect/token'
85
86
  //keycloakConfig["auth-server-url"] +'realms
86
87
  let config = {
@@ -114,6 +115,8 @@ class KeycloakService extends Keycloak {
114
115
  var rptResponse = await requestController.httpRequest(config, true);
115
116
  if (rptResponse.data.access_token) {
116
117
  token = rptResponse.data.access_token;
118
+ refresh_token = rptResponse.data.refresh_token;
119
+
117
120
  var userToken = token;
118
121
  config.data.grant_type = keycloakConfig.GRANT_TYPE;
119
122
  config.data.token = token;
@@ -158,6 +161,8 @@ class KeycloakService extends Keycloak {
158
161
  //Adding user custom attribute to our token object data.
159
162
  if (getuserDetails.data[0].attributes) {
160
163
  responseObject.attributes = getuserDetails.data[0].attributes;
164
+ } else {
165
+ responseObject.attributes = {};
161
166
  }
162
167
 
163
168
  delete config.headers.Authorization;
@@ -172,6 +177,7 @@ class KeycloakService extends Keycloak {
172
177
 
173
178
  let finalObject = {
174
179
  'token': userToken,
180
+ 'refresh_token': refresh_token,
175
181
  'keycloak_User': responseObject
176
182
  }
177
183
  resolve(finalObject);
@@ -1061,9 +1067,42 @@ class KeycloakService extends Keycloak {
1061
1067
  async createUser(username, password, token, userRoles) {
1062
1068
 
1063
1069
  let assignRole = [];
1070
+ let assignGroups = ['agents', 'default'];
1064
1071
 
1065
1072
  return new Promise(async (resolve, reject) => {
1066
1073
 
1074
+
1075
+ for (let group of assignGroups) {
1076
+
1077
+ let URL2 = keycloakConfig["auth-server-url"] + 'admin/realms/' + keycloakConfig.realm + '/groups?search=' + group;
1078
+
1079
+ let config1 = {
1080
+ method: 'get',
1081
+ url: URL2,
1082
+ headers: {
1083
+ 'Content-Type': 'application/json',
1084
+ 'Authorization': `Bearer ${token}`
1085
+ }
1086
+ };
1087
+
1088
+ try {
1089
+ let groupData = await requestController.httpRequest(config1, true);
1090
+
1091
+ if (groupData.data.length == 0) {
1092
+
1093
+ let createdGroup = await this.createGroup(token, group);
1094
+
1095
+ }
1096
+ } catch (err) {
1097
+ reject({
1098
+ "status": err.response.status,
1099
+ "message": err.response.data.error_description
1100
+ });
1101
+ }
1102
+
1103
+ }
1104
+
1105
+
1067
1106
  let URL = `${keycloakConfig["auth-server-url"]}${keycloakConfig["USERNAME_ADMIN"]}/realms/${keycloakConfig["realm"]}/users`;
1068
1107
 
1069
1108
  let data = {
@@ -1075,11 +1114,10 @@ class KeycloakService extends Keycloak {
1075
1114
  value: password,
1076
1115
  temporary: false
1077
1116
  }
1078
- ]
1117
+ ],
1118
+ groups: ["agents", "default"]
1079
1119
  }
1080
1120
 
1081
-
1082
-
1083
1121
  let config = {
1084
1122
  method: 'post',
1085
1123
  url: URL,
@@ -1145,6 +1183,43 @@ class KeycloakService extends Keycloak {
1145
1183
  });
1146
1184
  }
1147
1185
 
1186
+ async createGroup(adminToken, groupName) {
1187
+
1188
+ return new Promise(async (resolve, reject) => {
1189
+
1190
+ let URL = `${keycloakConfig["auth-server-url"]}${keycloakConfig["USERNAME_ADMIN"]}/realms/${keycloakConfig["realm"]}/groups`;
1191
+
1192
+ let data = {
1193
+ name: groupName
1194
+ }
1195
+
1196
+
1197
+ let config = {
1198
+ method: 'post',
1199
+ url: URL,
1200
+ headers: {
1201
+ 'Authorization': `Bearer ${adminToken}`
1202
+ },
1203
+ data: data
1204
+ };
1205
+
1206
+ try {
1207
+
1208
+ let createdGroup = await requestController.httpRequest(config, false);
1209
+ resolve(createdGroup.data);
1210
+
1211
+ }
1212
+ catch (err) {
1213
+ reject({
1214
+ "status": err.response.status,
1215
+ "message": err.response.data.error_description
1216
+ });
1217
+ }
1218
+
1219
+ });
1220
+
1221
+ }
1222
+
1148
1223
  //Authenticating Finesse User
1149
1224
  async authenticateFinesse(username, password, finesseUrl, userRoles, finesseToken) {
1150
1225
 
@@ -1272,6 +1347,56 @@ class KeycloakService extends Keycloak {
1272
1347
  }
1273
1348
  }
1274
1349
 
1350
+ async generateAccessTokenFromRefreshToken(refreshToken) {
1351
+
1352
+ return new Promise(async (resolve, reject) => {
1353
+ let accessToken;
1354
+ var URL = keycloakConfig["auth-server-url"] + 'realms/' + keycloakConfig.realm + '/protocol/openid-connect/token'
1355
+
1356
+ var config = {
1357
+ method: 'post',
1358
+ url: URL,
1359
+ headers: {
1360
+ 'Content-Type': 'application/x-www-form-urlencoded'
1361
+ },
1362
+ data: {
1363
+ client_id: keycloakConfig.CLIENT_ID,
1364
+ client_secret: keycloakConfig.credentials.secret,
1365
+ grant_type: 'refresh_token',
1366
+ refresh_token: refreshToken
1367
+ }
1368
+ };
1369
+
1370
+ try {
1371
+ let refreshTokenResponse = await requestController.httpRequest(config, true);
1372
+
1373
+ let accessToken = refreshTokenResponse.data.access_token;
1374
+ resolve({
1375
+ 'status': 200,
1376
+ 'access_token': accessToken
1377
+ });
1378
+
1379
+ } catch (error) {
1380
+
1381
+ if (error.response) {
1382
+
1383
+ if (error.response.data.error_description == 'Token is not active') {
1384
+ error.response.data.error_description = 'Refresh Token expired, please login again';
1385
+ }
1386
+
1387
+ reject({
1388
+ 'status': error.response.status,
1389
+ 'message': `${error.response.data.error_description}`
1390
+ });
1391
+
1392
+ } else {
1393
+ reject({ 'message': error.message });
1394
+ }
1395
+ }
1396
+
1397
+ });
1398
+ }
1399
+
1275
1400
  async checkErrorType(err) {
1276
1401
 
1277
1402
  if (err.code == "ETIMEDOUT") {
@@ -116,7 +116,8 @@ class TeamsService {
116
116
  'team': {
117
117
  'teamId': id,
118
118
  'teamName': name
119
- }
119
+ },
120
+ 'attributes': (user.attributes) ? user.attributes : {}
120
121
  });
121
122
  }
122
123