@itentialopensource/adapter-utils 5.5.0 → 5.6.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/CHANGELOG.md CHANGED
@@ -1,4 +1,22 @@
1
1
 
2
+ ## 5.6.0 [07-31-2024]
3
+
4
+ * Add abilities to refresh token and set msa query
5
+
6
+ Closes ADAPT-3629
7
+
8
+ See merge request itentialopensource/adapter-utils!294
9
+
10
+ ---
11
+
12
+ ## 5.5.1 [07-30-2024]
13
+
14
+ * Fix gzip conditional in propertyUtils
15
+
16
+ See merge request itentialopensource/adapter-utils!295
17
+
18
+ ---
19
+
2
20
  ## 5.5.0 [05-30-2024]
3
21
 
4
22
  * Add support for gzip responsedatatype
@@ -0,0 +1,9 @@
1
+ {
2
+ "ComplianceEntries": [
3
+ {
4
+ "name": "Compliance Summary",
5
+ "numInvalidProjects": 0,
6
+ "numValidProjects": 0
7
+ }
8
+ ]
9
+ }
@@ -0,0 +1,5 @@
1
+ ---------------------------------------------------------------------------------------------
2
+ **** Project Compliance Summary ****
3
+ 0 project(s) are not valid
4
+ 0 project(s) are valid
5
+ ---------------------------------------------------------------------------------------------
@@ -108,6 +108,9 @@ const healthchecklock = 0;
108
108
  let encodeUri = true;
109
109
  let authQueryEncode = null;
110
110
  let addCreds = true;
111
+ let refTokenReq = null;
112
+ let refTokenTimeout = -1;
113
+ let runRefreshToken = false;
111
114
 
112
115
  // Other global variables
113
116
  let id = null;
@@ -1269,6 +1272,7 @@ async function getToken(reqPath, options, tokenSchema, bodyString, callPropertie
1269
1272
  const currResult = {
1270
1273
  token: null,
1271
1274
  tokenp2: null,
1275
+ refreshToken: null,
1272
1276
  front: tokenSchema.responseSchema.properties.token.front,
1273
1277
  end: tokenSchema.responseSchema.properties.token.end
1274
1278
  };
@@ -1558,6 +1562,10 @@ async function getToken(reqPath, options, tokenSchema, bodyString, callPropertie
1558
1562
  && tokenSchema.responseSchema.properties.expires.placement && tokenSchema.responseSchema.properties.expires.placement.toUpperCase() === 'BODY') {
1559
1563
  currResult.expires = translated.expires;
1560
1564
  }
1565
+ if (tokenSchema.responseSchema && tokenSchema.responseSchema.properties && tokenSchema.responseSchema.properties.refreshToken
1566
+ && tokenSchema.responseSchema.properties.refreshToken.placement && tokenSchema.responseSchema.properties.refreshToken.placement.toUpperCase() === 'BODY') {
1567
+ currResult.refreshToken = translated.refreshToken;
1568
+ }
1561
1569
  // return the token that we find in the translated object
1562
1570
  return resolve(currResult);
1563
1571
  });
@@ -1587,6 +1595,9 @@ async function buildTokenRequest(reqPath, reqBody, callProperties, callback) {
1587
1595
  if (callProperties && callProperties.mfa) {
1588
1596
  entity = callProperties.mfa.stepAtionName;
1589
1597
  }
1598
+ if (runRefreshToken) {
1599
+ entity = 'getRefreshToken';
1600
+ }
1590
1601
  // Get the entity schema from the file system
1591
1602
  return propUtilInst.getEntitySchema('.system', entity, choosepath, this.dbUtil, async (tokenSchema, healthError) => {
1592
1603
  if (healthError || !tokenSchema || Object.keys(tokenSchema).length === 0) {
@@ -2062,19 +2073,37 @@ async function buildTokenRequest(reqPath, reqBody, callProperties, callback) {
2062
2073
  options.path = options.path.replace('{password}', usePass);
2063
2074
  }
2064
2075
 
2065
- // if this is not a get, need to add the info to the request
2066
2076
  let creds = {};
2067
- if (authMethod === 'multi_step_authentication') {
2068
- const { stepBody, stepHeaders } = callProperties.mfa;
2077
+ if (authMethod === 'multi_step_authentication' && !runRefreshToken) {
2078
+ const { stepBody, stepHeaders, stepQuery } = callProperties.mfa;
2069
2079
  Object.assign(creds, stepBody);
2070
2080
  Object.assign(options.headers, stepHeaders);
2081
+ // If there are query variables, add them to the path
2082
+ if (Object.keys(stepQuery).length > 0) {
2083
+ let mfaQueryString = '';
2084
+ if (encodeUri === true) {
2085
+ mfaQueryString += querystring.stringify(stepQuery);
2086
+ } else {
2087
+ const mfaQqueryKeys = Object.keys(stepQuery);
2088
+ for (let k = 0; k < mfaQqueryKeys.length; k += 1) {
2089
+ if (k > 0) {
2090
+ mfaQueryString += '&';
2091
+ }
2092
+ mfaQueryString += `${mfaQqueryKeys[k]}=${stepQuery[mfaQqueryKeys[k]]}`;
2093
+ }
2094
+ }
2095
+ // append to the path
2096
+ if (options.path.indexOf('?') < 0) {
2097
+ options.path = `${options.path}?${mfaQueryString}`;
2098
+ } else {
2099
+ options.path = `${options.path}&${mfaQueryString}`;
2100
+ }
2101
+ }
2071
2102
  }
2103
+
2104
+ // if this is not a get, need to add the info to the request
2072
2105
  if (options.method !== 'GET') {
2073
- if (authMethod === 'multi_step_authentication') {
2074
- const { stepBody, stepHeaders } = callProperties.mfa;
2075
- Object.assign(creds, stepBody);
2076
- Object.assign(options.headers, stepHeaders);
2077
- } else {
2106
+ if (authMethod !== 'multi_step_authentication') {
2078
2107
  creds = {
2079
2108
  username: useUser,
2080
2109
  password: usePass
@@ -2139,6 +2168,34 @@ async function buildTokenRequest(reqPath, reqBody, callProperties, callback) {
2139
2168
  }
2140
2169
  }
2141
2170
 
2171
+ // Update request info if run refresh token
2172
+ if (runRefreshToken && callProperties.refRequest && Object.keys(callProperties.refRequest).length > 0) {
2173
+ const { headers, query, body } = callProperties.refRequest;
2174
+ Object.assign(options.headers, headers);
2175
+ Object.assign(creds, body);
2176
+ // If there are query variables, add them to the path
2177
+ if (Object.keys(query).length > 0) {
2178
+ let refTokenQueryString = '';
2179
+ if (encodeUri === true) {
2180
+ refTokenQueryString += querystring.stringify(query);
2181
+ } else {
2182
+ const refTokenQueryKeys = Object.keys(query);
2183
+ for (let k = 0; k < refTokenQueryKeys.length; k += 1) {
2184
+ if (k > 0) {
2185
+ refTokenQueryString += '&';
2186
+ }
2187
+ refTokenQueryString += `${refTokenQueryKeys[k]}=${query[refTokenQueryKeys[k]]}`;
2188
+ }
2189
+ }
2190
+ // append to the path
2191
+ if (options.path.indexOf('?') < 0) {
2192
+ options.path = `${options.path}?${refTokenQueryString}`;
2193
+ } else {
2194
+ options.path = `${options.path}&${refTokenQueryString}`;
2195
+ }
2196
+ }
2197
+ }
2198
+
2142
2199
  // map the data we received to an Entity - will get back the defaults
2143
2200
  const tokenEntity = transUtilInst.mapToOutboundEntity(creds, tokenSchema.requestSchema);
2144
2201
  bodyString = tokenEntity;
@@ -2267,7 +2324,12 @@ function addTokenItem(user, reqBody, token, timeout, callback) {
2267
2324
 
2268
2325
  // add the token item to the tokenlist and return it
2269
2326
  if (tokenCache === 'local') {
2270
- tokenList.push(tokenItem);
2327
+ const index = tokenList.findIndex((obj) => obj.tkey === tokenItem.tkey);
2328
+ if (index === -1) {
2329
+ tokenList.push(tokenItem);
2330
+ } else {
2331
+ tokenList[index] = tokenItem;
2332
+ }
2271
2333
  return callback(token);
2272
2334
  }
2273
2335
 
@@ -2344,13 +2406,21 @@ function validToken(user, reqBody, invalidToken, callback) {
2344
2406
  if (tokenList[i].tkey === tkey) {
2345
2407
  // if the token expired (or will expire within a minute),
2346
2408
  // or it is invalid (failed) remove it from the token list
2347
- if (tokenList[i].expire < expireCheck
2348
- || tokenList[i].token.token === invalidToken) {
2409
+ if ((tokenList[i].expire < expireCheck
2410
+ || tokenList[i].token.token === invalidToken) && !tokenList[i].token.refreshToken) {
2349
2411
  tokenList.splice(i, 1);
2350
2412
  break;
2413
+ } else if ((tokenList[i].expire < expireCheck
2414
+ || tokenList[i].token.token === invalidToken) && tokenList[i].token.refreshToken) {
2415
+ // Just keep refreshToken for future token refresh
2416
+ delete tokenList[i].expire;
2417
+ delete tokenList[i].token.token;
2418
+ delete tokenList[i].token.tokenp2;
2419
+ break;
2420
+ }
2421
+ if (tokenList[i].token.token || tokenList[i].token.tokenp2) {
2422
+ retToken = tokenList[i].token;
2351
2423
  }
2352
-
2353
- retToken = tokenList[i].token;
2354
2424
  break;
2355
2425
  }
2356
2426
  }
@@ -2362,6 +2432,71 @@ function validToken(user, reqBody, invalidToken, callback) {
2362
2432
  }
2363
2433
  }
2364
2434
 
2435
+ /*
2436
+ * INTERNAL FUNCTION: retrieve the refresh token from cache and determine if
2437
+ * it valid. if valid, return it otherwise return null
2438
+ */
2439
+ function validRefreshToken(user, reqBody, invalidToken, callback) {
2440
+ const origin = `${id}-connectorRest-validRefreshToken`;
2441
+ log.trace(origin);
2442
+
2443
+ try {
2444
+ // get the token from redis
2445
+ let tkey = `${id}__%%__${user}`;
2446
+
2447
+ if (reqBody) {
2448
+ tkey += `__%%__${JSON.stringify(reqBody)}`;
2449
+ }
2450
+
2451
+ if (refTokenReq && refTokenReq.refresh_token && refTokenReq.refresh_token.token_timeout) {
2452
+ refTokenTimeout = refTokenReq.refresh_token.token_timeout;
2453
+ }
2454
+
2455
+ // Return null if refresh token timeout is -1
2456
+ if (refTokenTimeout === -1) {
2457
+ return callback(null);
2458
+ }
2459
+
2460
+ const currentTime = new Date().getTime();
2461
+
2462
+ // To check if refresh token will expire within a minute
2463
+ const refTokenTimeoutMillis = refTokenTimeout - 60000;
2464
+
2465
+ let refToken = null;
2466
+
2467
+ // find user's refresh token in the list
2468
+ for (let i = 0; i < tokenList.length; i += 1) {
2469
+ if (tokenList[i].tkey === tkey) {
2470
+ if (currentTime - tokenList[i].start < refTokenTimeoutMillis && tokenList[i].token.refreshToken) {
2471
+ refToken = tokenList[i].token.refreshToken;
2472
+ break;
2473
+ }
2474
+ break;
2475
+ }
2476
+ }
2477
+ return callback(refToken);
2478
+ } catch (e) {
2479
+ // handle any exception
2480
+ const errorObj = transUtilInst.checkAndReturn(e, origin, 'Issue validating cached refresh token');
2481
+ return callback(null, errorObj);
2482
+ }
2483
+ }
2484
+
2485
+ function getCachedRefToken(cachedTokenIdentifier, invalidToken) {
2486
+ const origin = `${id}-connectorRest-getCachedRefToken`;
2487
+ log.trace(origin);
2488
+
2489
+ return new Promise((resolve, reject) => {
2490
+ validRefreshToken(id, cachedTokenIdentifier, invalidToken, (refToken, error) => {
2491
+ if (error) {
2492
+ reject(error);
2493
+ } else {
2494
+ resolve(refToken);
2495
+ }
2496
+ });
2497
+ });
2498
+ }
2499
+
2365
2500
  /*
2366
2501
  * INTERNAL FUNCTION: getTokenItem is used to retrieve a token items from
2367
2502
  * memory based on the user provided
@@ -2382,6 +2517,27 @@ function getTokenItem(pathForToken, user, reqBody, invalidToken, callProperties,
2382
2517
  if (retToken !== null) {
2383
2518
  done(retToken, null);
2384
2519
  } else {
2520
+ // If primary token not found or invalid, check if there is refresh token
2521
+ validRefreshToken(user, reqBody, invalidToken, (refToken, rerror) => {
2522
+ if (rerror) {
2523
+ done(null, rerror);
2524
+ }
2525
+ if (refToken !== null) {
2526
+ log.debug(`${origin}-returning cached refresh token`);
2527
+ if (!callProperties) {
2528
+ callProperties = {};
2529
+ }
2530
+ callProperties.refRequest = {};
2531
+ buildRefTokenData(refToken, callProperties);
2532
+ // Check if getRefreshToken entity exists
2533
+ propUtilInst.getEntitySchema('.system', 'getRefreshToken', choosepath, this.dbUtil, async (tokenSchema, error) => {
2534
+ // Refresh the token if getRefreshToken entity exists
2535
+ if (tokenSchema) {
2536
+ runRefreshToken = true;
2537
+ }
2538
+ });
2539
+ } else runRefreshToken = false;
2540
+ });
2385
2541
  // No valid token found, Need to get a new token and add it to the token list
2386
2542
  buildTokenRequest(pathForToken, reqBody, callProperties, (dyntoken, berror) => {
2387
2543
  if (berror) {
@@ -2405,7 +2561,8 @@ function getTokenItem(pathForToken, user, reqBody, invalidToken, callProperties,
2405
2561
 
2406
2562
  const tokenObj = {
2407
2563
  token: findPrimaryTokenInResult(dyntoken, dyntoken.front, dyntoken.end),
2408
- tokenp2: findSecondaryTokenInResult(dyntoken, dyntoken.front, dyntoken.end)
2564
+ tokenp2: findSecondaryTokenInResult(dyntoken, dyntoken.front, dyntoken.end),
2565
+ refreshToken: dyntoken.refreshToken
2409
2566
  };
2410
2567
 
2411
2568
  // if this is worth caching
@@ -2679,6 +2836,24 @@ function buildMfaSso(prop, mfaStepConfiguration, callProperties) {
2679
2836
  }
2680
2837
  }
2681
2838
 
2839
+ function buildMfaQuery(prop, mfaStepConfiguration, callProperties) {
2840
+ const origin = `${id}-connectorRest-buildMfaQuery`;
2841
+ log.trace(origin);
2842
+ const fullPropertyValue = mfaStepConfiguration.requestFields[prop];
2843
+ // Check if fullPropertyValue has reference in curly braces (e.g., {getSession.responseFields.session})
2844
+ let propertyValue = fullPropertyValue;
2845
+ const matching = searchTextInCurlyBraces(fullPropertyValue);
2846
+ const queryParam = prop.split('.')[1];
2847
+ if (matching) {
2848
+ const matchedText = matching[0];
2849
+ propertyValue = matching[1];
2850
+ const resolvedValue = getReferencedMfaValue(propertyValue);
2851
+ callProperties.mfa.stepQuery[queryParam] = fullPropertyValue.replace(matchedText, resolvedValue);
2852
+ } else {
2853
+ callProperties.mfa.stepQuery[queryParam] = mfaStepConfiguration.requestFields[prop];
2854
+ }
2855
+ }
2856
+
2682
2857
  /* */
2683
2858
  function getReferencedMfaValue(propertyValue) {
2684
2859
  const origin = `${id}-connectorRest-getReferencedMfaValue`;
@@ -2702,6 +2877,7 @@ function buildMfaStepData(step, callProperties) {
2702
2877
  const mfaStepConfiguration = multiStepAuthCalls[step];
2703
2878
  callProperties.mfa.stepBody = {};
2704
2879
  callProperties.mfa.stepHeaders = {};
2880
+ callProperties.mfa.stepQuery = {};
2705
2881
  if (mfaStepConfiguration.sso) {
2706
2882
  callProperties.mfa.host = '';
2707
2883
  callProperties.mfa.port = '';
@@ -2715,6 +2891,8 @@ function buildMfaStepData(step, callProperties) {
2715
2891
  Object.keys(mfaStepConfiguration.requestFields).forEach((prop) => {
2716
2892
  if (prop.startsWith('header')) {
2717
2893
  buildMfaHeader(prop, mfaStepConfiguration, callProperties);
2894
+ } else if (prop.startsWith('query')) {
2895
+ buildMfaQuery(prop, mfaStepConfiguration, callProperties);
2718
2896
  } else {
2719
2897
  buildMfaBody(prop, mfaStepConfiguration, callProperties);
2720
2898
  }
@@ -2722,6 +2900,35 @@ function buildMfaStepData(step, callProperties) {
2722
2900
  }
2723
2901
  }
2724
2902
 
2903
+ function buildRefTokenData(cachedRefToken, callProperties) {
2904
+ const origin = `${id}-connectorRest-buildRefTokenData`;
2905
+ log.trace(origin);
2906
+ if (refTokenReq && refTokenReq.requestFields && Object.keys(refTokenReq.requestFields).length > 0) {
2907
+ callProperties.refRequest.headers = {};
2908
+ callProperties.refRequest.query = {};
2909
+ callProperties.refRequest.body = {};
2910
+ Object.keys(refTokenReq.requestFields).forEach((prop) => {
2911
+ if (prop.startsWith('header')) {
2912
+ const headerName = prop.split('.')[1];
2913
+ callProperties.refRequest.headers[headerName] = refTokenReq.requestFields[prop];
2914
+ } else if (prop.startsWith('query')) {
2915
+ const queryName = prop.split('.')[1];
2916
+ callProperties.refRequest.query[queryName] = refTokenReq.requestFields[prop];
2917
+ } else {
2918
+ callProperties.refRequest.body[prop] = refTokenReq.requestFields[prop];
2919
+ }
2920
+ });
2921
+ }
2922
+
2923
+ if (refTokenReq && refTokenReq.refresh_token && Object.keys(refTokenReq.refresh_token).length > 0) {
2924
+ if (refTokenReq.refresh_token.placement && refTokenReq.refresh_token.placement.toLowerCase() === 'query') {
2925
+ callProperties.refRequest.query.refreshToken = cachedRefToken;
2926
+ } else {
2927
+ callProperties.refRequest.body.refreshToken = cachedRefToken;
2928
+ }
2929
+ }
2930
+ }
2931
+
2725
2932
  /* */
2726
2933
  async function translateMfaStepResult(step, stepResult, callProperties) {
2727
2934
  const origin = `${id}-connectorRest-translateMfaStepResult`;
@@ -2738,7 +2945,7 @@ async function translateMfaStepResult(step, stepResult, callProperties) {
2738
2945
  allProperties.forEach((prop) => {
2739
2946
  if (Object.prototype.hasOwnProperty.call(stepResult, prop)) {
2740
2947
  const externalName = tokenSchema.responseSchema.properties[prop].external_name;
2741
- if (!stepResult[prop]) {
2948
+ if (!stepResult[prop] && prop !== 'refreshToken') {
2742
2949
  log.error(`No step-${step + 1} result for responseSchema (prop=>external_name): (${prop}=>${externalName}) found in step response`);
2743
2950
  return reject(new Error(`Response schema for step-${step + 1} misconfiguration`));
2744
2951
  }
@@ -2820,8 +3027,43 @@ async function getMfaFinalTokens(request, callProperties, invalidToken) {
2820
3027
  log.debug(`${origin}-returning cached MFA token`);
2821
3028
  finalTokens = cachedToken;
2822
3029
  return;
2823
- } mfaStepsResults.length = 0;
2824
- // no cached token found, trigger auth steps to obtain new token
3030
+ }
3031
+ // Get cached refresh token if primary token is not valid
3032
+ const cachedRefToken = await getCachedRefToken(cachedTokenIdentifier, invalidToken)
3033
+ .catch((error) => {
3034
+ log.error(error);
3035
+ throw error;
3036
+ });
3037
+ if (cachedRefToken) {
3038
+ log.debug(`${origin}-returning cached MFA refresh token`);
3039
+ if (!callProperties) {
3040
+ callProperties = {};
3041
+ }
3042
+ callProperties.refRequest = {};
3043
+ buildRefTokenData(cachedRefToken, callProperties);
3044
+ propUtilInst.getEntitySchema('.system', 'getRefreshToken', choosepath, this.dbUtil, async (tokenSchema, error) => {
3045
+ if (error || !tokenSchema || Object.keys(tokenSchema).length === 0) {
3046
+ tokenSchema = null;
3047
+ }
3048
+ // If cached refresh token is valid and there is action for getRefreshToken, run refresh token
3049
+ if (tokenSchema) {
3050
+ runRefreshToken = true;
3051
+ }
3052
+ });
3053
+ if (runRefreshToken) {
3054
+ finalTokens = await buildTokenRequest(request.header.path, request.authData, callProperties).catch((error) => { // eslint-disable-line no-await-in-loop
3055
+ log.error(error);
3056
+ throw error;
3057
+ });
3058
+ if (finalTokens) {
3059
+ await cacheMfaToken(cachedTokenIdentifier, finalTokens).catch((error) => log.error(error));
3060
+ }
3061
+ return;
3062
+ }
3063
+ }
3064
+ runRefreshToken = false;
3065
+ mfaStepsResults.length = 0;
3066
+ // no cached primary token or refresh token found, trigger auth steps to obtain new token
2825
3067
  for (let step = 0; step < multiStepAuthCalls.length; step += 1) {
2826
3068
  const stepAtionName = `MFA_Step_${step + 1}`;
2827
3069
  log.debug(`${origin}-Executing MFA step-${step + 1}, action: ${stepAtionName}`);
@@ -4028,6 +4270,11 @@ class ConnectorRest {
4028
4270
  if (typeof props.authentication.addCreds === 'boolean') {
4029
4271
  addCreds = props.authentication.addCreds;
4030
4272
  }
4273
+
4274
+ // set the refresh token request (optional - default is null)
4275
+ if (props.authentication.refresh_token_request && typeof props.authentication.refresh_token_request === 'object') {
4276
+ refTokenReq = props.authentication.refresh_token_request;
4277
+ }
4031
4278
  }
4032
4279
 
4033
4280
  // set the stub mode (optional - default is false)
@@ -527,11 +527,15 @@ class AdapterPropertyUtil {
527
527
  // need to make sure we have supported datatypes - PLAIN is best if not supported - no translation or encoding
528
528
  if (entitySchema.requestDatatype.toUpperCase() !== 'JSON' && entitySchema.requestDatatype.toUpperCase() !== 'XML'
529
529
  && entitySchema.requestDatatype.toUpperCase() !== 'URLENCODE' && entitySchema.requestDatatype.toUpperCase() !== 'URLQUERY'
530
- && entitySchema.requestDatatype.toUpperCase() !== 'FORM' && entitySchema.requestDatatype.toUpperCase() !== 'JSON2XML') {
530
+ && entitySchema.requestDatatype.toUpperCase() !== 'FORM' && entitySchema.requestDatatype.toUpperCase() !== 'JSON2XML'
531
+ && entitySchema.requestDatatype.toUpperCase() !== 'GZIP2XML2JSON' && entitySchema.requestDatatype.toUpperCase() !== 'GZIP2XML'
532
+ && entitySchema.requestDatatype.toUpperCase() !== 'GZIP2JSON') {
531
533
  entitySchema.requestDatatype = 'PLAIN';
532
534
  }
533
535
  if (entitySchema.responseDatatype.toUpperCase() !== 'JSON' && entitySchema.responseDatatype.toUpperCase() !== 'XML'
534
- && entitySchema.responseDatatype.toUpperCase() !== 'URLENCODE' && entitySchema.responseDatatype.toUpperCase() !== 'XML2JSON') {
536
+ && entitySchema.responseDatatype.toUpperCase() !== 'URLENCODE' && entitySchema.responseDatatype.toUpperCase() !== 'XML2JSON'
537
+ && entitySchema.requestDatatype.toUpperCase() !== 'GZIP2XML2JSON' && entitySchema.requestDatatype.toUpperCase() !== 'GZIP2XML'
538
+ && entitySchema.requestDatatype.toUpperCase() !== 'GZIP2JSON') {
535
539
  entitySchema.responseDatatype = 'PLAIN';
536
540
  }
537
541
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itentialopensource/adapter-utils",
3
- "version": "5.5.0",
3
+ "version": "5.6.0",
4
4
  "description": "Itential Adapter Utility Libraries",
5
5
  "scripts": {
6
6
  "postinstall": "node utils/setup.js",
@@ -27,7 +27,7 @@
27
27
  "dependencies": {
28
28
  "ajv": "^8.12.0",
29
29
  "async-lock": "^1.4.0",
30
- "aws-sdk": "^2.1363.0",
30
+ "aws-sdk": "^2.1665.0",
31
31
  "aws4": "^1.9.1",
32
32
  "cookie": "^0.5.0",
33
33
  "crypto-js": "^4.1.1",
Binary file