@mimik/oauth-helper 4.0.2 → 4.1.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/README.md CHANGED
@@ -1,18 +1,3 @@
1
- ## Modules
2
-
3
- <dl>
4
- <dt><a href="#module_oauth-helper">oauth-helper</a></dt>
5
- <dd></dd>
6
- </dl>
7
-
8
- ## Typedefs
9
-
10
- <dl>
11
- <dt><a href="#requestCallback">requestCallback</a> : <code>function</code></dt>
12
- <dd><p>This callback is displayed as a global member.</p>
13
- </dd>
14
- </dl>
15
-
16
1
  <a name="module_oauth-helper"></a>
17
2
 
18
3
  ## oauth-helper
@@ -22,8 +7,28 @@ import oauthHelper from '@mimik/oauth-helper';
22
7
  ```
23
8
 
24
9
  * [oauth-helper](#module_oauth-helper)
25
- * [~rpAuth(type, options)](#module_oauth-helper..rpAuth) ⇒ <code>Promise</code>
26
- * [~authProfile(method, id, correlationId, options)](#module_oauth-helper..authProfile) ⇒ <code>Promise</code>
10
+ * [~oauthHelper(config)](#module_oauth-helper..oauthHelper) ⇒ <code>object</code>
11
+ * _async_
12
+ * [~rpAuth(type, options)](#module_oauth-helper..rpAuth) ⇒ <code>Promise</code>
13
+ * [~authProfile(method, id, correlationId, [options])](#module_oauth-helper..authProfile) ⇒ <code>Promise</code>
14
+
15
+ <a name="module_oauth-helper..oauthHelper"></a>
16
+
17
+ ### oauth-helper~oauthHelper(config) ⇒ <code>object</code>
18
+ Create an OAuth helper instance for making authorized requests.
19
+
20
+ **Kind**: inner method of [<code>oauth-helper</code>](#module_oauth-helper)
21
+ **Returns**: <code>object</code> - Object with `rpAuth` and `authProfile` methods.
22
+
23
+ | Param | Type | Description |
24
+ | --- | --- | --- |
25
+ | config | <code>object</code> | Service configuration. |
26
+ | config.security | <code>object</code> | Security settings. |
27
+ | config.security.server | <code>object</code> | Token server configuration. |
28
+ | config.security.server.issuer | <code>string</code> | Token issuer URL. |
29
+ | config.security.server.id | <code>string</code> | Client ID. |
30
+ | config.security.server.secret | <code>string</code> | Client secret. |
31
+ | config.dependencies | <code>object</code> | Dependency type to settings map. Each entry must have an `audience` string. |
27
32
 
28
33
  <a name="module_oauth-helper..rpAuth"></a>
29
34
 
@@ -31,24 +36,24 @@ import oauthHelper from '@mimik/oauth-helper';
31
36
  Make an authorized request.
32
37
 
33
38
  **Kind**: inner method of [<code>oauth-helper</code>](#module_oauth-helper)
34
- **Returns**: <code>Promise</code> - .
39
+ **Returns**: <code>Promise</code> - Resolves with the response from the authorized request.
35
40
  **Category**: async
36
41
  **Throws**:
37
42
 
38
- - <code>Promise</code> Will throw the same error than [request-promise](https://www.npmjs.com/package/request-promise).
43
+ - <code>Error</code> Will throw the same error as [request-promise](https://www.npmjs.com/package/request-promise).
39
44
 
40
45
  The property `token` may be added to `options`, in order to set up how the token is retrieved from the token manager. The structure is:
41
46
  ```
42
47
  {
43
48
  "retry": "object to specify how the retry to the token manager will be done. similar to rp-retry retry property",
44
- "customerName": "name of the customer for which the token is entended for, see mST API",
49
+ "customerName": "name of the customer for which the token is intended, see mST API",
45
50
  "cluster": "to set the token to be a cluster token"
46
51
  }
47
- ````
48
- The property `metrics` may be added to `options`, in order to setup metrics about calls made to other microservice. The structure is:
52
+ ```
53
+ The property `metrics` may be added to `options`, in order to set up metrics about calls made to other microservice. The structure is:
49
54
  ```
50
55
  {
51
- "HTTPrequestDuration": "prom-client function to label and record the elapsed time",
56
+ "HTTPRequestDuration": "prom-client function to label and record the elapsed time",
52
57
  "url": "url to be displayed for the metrics. If not present the url of the options will be used"
53
58
  }
54
59
  ```
@@ -63,15 +68,15 @@ The property `metrics` may be added to `options`, in order to setup metrics abou
63
68
 
64
69
  <a name="module_oauth-helper..authProfile"></a>
65
70
 
66
- ### oauth-helper~authProfile(method, id, correlationId, options) ⇒ <code>Promise</code>
71
+ ### oauth-helper~authProfile(method, id, correlationId, [options]) ⇒ <code>Promise</code>
67
72
  Make an authProfile request to mID.
68
73
 
69
74
  **Kind**: inner method of [<code>oauth-helper</code>](#module_oauth-helper)
70
- **Returns**: <code>Promise</code> - .
75
+ **Returns**: <code>Promise</code> - Resolves with the response from mID.
71
76
  **Category**: async
72
77
  **Throws**:
73
78
 
74
- - <code>Promise</code> Will throw a rich error is the request fails or an error if the id is not identified
79
+ - <code>Error</code> Will throw a rich error if the request fails or an error if the id is not identified
75
80
 
76
81
  **Requires**: <code>module:@mimik/sumologic-winston-logger</code>
77
82
  **Fulfil**: <code>object</code> The response of the request made to `mID`.
@@ -79,18 +84,7 @@ Make an authProfile request to mID.
79
84
  | Param | Type | Description |
80
85
  | --- | --- | --- |
81
86
  | method | <code>string</code> | Method (`GET`, `DELETE`) of the request to be made. |
82
- | id | <code>string</code> | `UserId` to associated witht the request. |
83
- | correlationId | <code>UUID.&lt;string&gt;</code> | CorrelationId to associated with the request. |
84
- | options | <code>object</code> | Options to be added to the request. metrics can then be added to the options. |
85
-
86
- <a name="requestCallback"></a>
87
-
88
- ## requestCallback : <code>function</code>
89
- This callback is displayed as a global member.
90
-
91
- **Kind**: global typedef
92
-
93
- | Param | Type | Description |
94
- | --- | --- | --- |
95
- | either | <code>object</code> | `null` or an `error`. |
87
+ | id | <code>string</code> | `UserId` associated with the request. |
88
+ | correlationId | <code>string</code> | CorrelationId associated with the request. |
89
+ | [options] | <code>object</code> | Options to be added to the request. metrics can then be added to the options. |
96
90
 
package/index.js CHANGED
@@ -16,7 +16,7 @@ Promise.config({ cancellation: true });
16
16
 
17
17
  const TOKEN_REFRESH_TOLERANCE = 900; // in seconds
18
18
  const CLUSTER = 'cluster';
19
- const CLIENT_CEDENTIALS = 'client_credentials';
19
+ const CLIENT_CREDENTIALS = 'client_credentials';
20
20
  const REFRESH_TOKEN = 'refresh_token';
21
21
 
22
22
  const PARAMETER_ERROR = 400;
@@ -37,13 +37,28 @@ const valid = (token) => {
37
37
  };
38
38
 
39
39
  const createToken = (value) => {
40
+ const decoded = jwt.decode(value);
41
+ if (!decoded) throw new Error(`failed to decode token: ${value}`);
40
42
  const token = {
41
43
  value,
42
- exp: jwt.decode(value).exp,
44
+ exp: decoded.exp,
43
45
  };
44
46
  return token;
45
47
  };
46
48
 
49
+ /**
50
+ * Create an OAuth helper instance for making authorized requests.
51
+ *
52
+ * @function oauthHelper
53
+ * @param {object} config - Service configuration.
54
+ * @param {object} config.security - Security settings.
55
+ * @param {object} config.security.server - Token server configuration.
56
+ * @param {string} config.security.server.issuer - Token issuer URL.
57
+ * @param {string} config.security.server.id - Client ID.
58
+ * @param {string} config.security.server.secret - Client secret.
59
+ * @param {object} config.dependencies - Dependency type to settings map. Each entry must have an `audience` string.
60
+ * @return {object} Object with `rpAuth` and `authProfile` methods.
61
+ */
47
62
  const oauthHelper = (config) => {
48
63
  const { server } = config.security;
49
64
  const getToken = (type, origin, correlationId, options) => {
@@ -57,7 +72,7 @@ const oauthHelper = (config) => {
57
72
  client_id: server.id,
58
73
  client_secret: server.secret,
59
74
  audience: config.dependencies[type].audience,
60
- grant_type: CLIENT_CEDENTIALS,
75
+ grant_type: CLIENT_CREDENTIALS,
61
76
  };
62
77
 
63
78
  if (options) {
@@ -71,6 +86,7 @@ const oauthHelper = (config) => {
71
86
  tokenOptions.metrics = { HTTPRequestDuration: options.metrics.HTTPRequestDuration, url: tokenOptions.url };
72
87
  }
73
88
  }
89
+ const metricsBaseUrl = tokenOptions.metrics ? tokenOptions.metrics.url : undefined;
74
90
  if (!tokens[type]) tokens[type] = {};
75
91
  if (!tokens[type][origin]) tokens[type][origin] = {};
76
92
  if (valid(tokens[type][origin].accessToken)) return Promise.resolve(tokens[type][origin].accessToken.value);
@@ -81,24 +97,24 @@ const oauthHelper = (config) => {
81
97
  grant_type: REFRESH_TOKEN,
82
98
  };
83
99
  if (tokenOptions.metrics) {
84
- tokenOptions.metrics.url = `${tokenOptions.metrics.url}/${REFRESH_TOKEN}`;
100
+ tokenOptions.metrics.url = `${metricsBaseUrl}/${REFRESH_TOKEN}`;
85
101
  }
86
102
  }
87
103
  else {
88
- logger.silly(`invalid ${REFRESH_TOKEN} trying ${CLIENT_CEDENTIALS}`, { type, origin }, correlationId);
104
+ logger.silly(`invalid ${REFRESH_TOKEN} trying ${CLIENT_CREDENTIALS}`, { type, origin }, correlationId);
89
105
  tokenOptions.body = getCredential;
90
106
  if (tokenOptions.metrics) {
91
- tokenOptions.metrics.url = `${tokenOptions.metrics.url}/${CLIENT_CEDENTIALS}`;
107
+ tokenOptions.metrics.url = `${metricsBaseUrl}/${CLIENT_CREDENTIALS}`;
92
108
  }
93
109
  }
94
110
  return rpRetry(tokenOptions).catch((err) => {
95
- if (err.statusCode !== PARAMETER_ERROR || tokenOptions.body.grant_type === CLIENT_CEDENTIALS) {
111
+ if (err.statusCode !== PARAMETER_ERROR || tokenOptions.body.grant_type === CLIENT_CREDENTIALS) {
96
112
  throw err;
97
113
  }
98
- logger.silly(`moving from ${REFRESH_TOKEN} to ${CLIENT_CEDENTIALS}`, { error: err.message }, correlationId);
114
+ logger.silly(`moving from ${REFRESH_TOKEN} to ${CLIENT_CREDENTIALS}`, { error: err.message }, correlationId);
99
115
  tokenOptions.body = getCredential;
100
116
  if (tokenOptions.metrics) {
101
- tokenOptions.metrics.url = `${tokenOptions.metrics.url}/${CLIENT_CEDENTIALS}`;
117
+ tokenOptions.metrics.url = `${metricsBaseUrl}/${CLIENT_CREDENTIALS}`;
102
118
  }
103
119
  return rpRetry(tokenOptions);
104
120
  }).then((response) => {
@@ -116,22 +132,22 @@ const oauthHelper = (config) => {
116
132
  * @category async
117
133
  * @param {string} type - Type of micro service to request.
118
134
  * @param {object} options - Options for the request. Similar to [request-promise](https://www.npmjs.com/package/request-promise) options.
119
- * @return {Promise}.
135
+ * @return {Promise} Resolves with the response from the authorized request.
120
136
  * @fulfil {object} - Response of the [request-promise](https://www.npmjs.com/package/request-promise) request.
121
- * @throws {Promise} Will throw the same error than [request-promise](https://www.npmjs.com/package/request-promise).
137
+ * @throws {Error} Will throw the same error as [request-promise](https://www.npmjs.com/package/request-promise).
122
138
  *
123
139
  * The property `token` may be added to `options`, in order to set up how the token is retrieved from the token manager. The structure is:
124
140
  * ```
125
141
  * {
126
142
  * "retry": "object to specify how the retry to the token manager will be done. similar to rp-retry retry property",
127
- * "customerName": "name of the customer for which the token is entended for, see mST API",
143
+ * "customerName": "name of the customer for which the token is intended, see mST API",
128
144
  * "cluster": "to set the token to be a cluster token"
129
145
  * }
130
- * ````
131
- * The property `metrics` may be added to `options`, in order to setup metrics about calls made to other microservice. The structure is:
146
+ * ```
147
+ * The property `metrics` may be added to `options`, in order to set up metrics about calls made to other microservice. The structure is:
132
148
  * ```
133
149
  * {
134
- * "HTTPrequestDuration": "prom-client function to label and record the elapsed time",
150
+ * "HTTPRequestDuration": "prom-client function to label and record the elapsed time",
135
151
  * "url": "url to be displayed for the metrics. If not present the url of the options will be used"
136
152
  * }
137
153
  * ```
@@ -163,10 +179,7 @@ const oauthHelper = (config) => {
163
179
 
164
180
  return getToken(type, url.origin, correlationId, options)
165
181
  .then((token) => {
166
- const opts = options;
167
-
168
- if (!opts.headers) opts.headers = {};
169
- opts.headers.authorization = `Bearer ${token}`;
182
+ const opts = { ...options, headers: { ...options.headers, authorization: `Bearer ${token}` } };
170
183
  return rpRetry(opts)
171
184
  .then((result) => {
172
185
  measure(OK);
@@ -174,9 +187,9 @@ const oauthHelper = (config) => {
174
187
  })
175
188
  .catch((err) => {
176
189
  if (err.statusCode === FORBIDDEN_ERROR) {
177
- logger.warn('got a unauthorized request, retrying', { error: err.message, type }, correlationId);
178
- tokens[type].accessToken = null;
179
- return getToken(type, options.uri || options.url, correlationId, options)
190
+ logger.warn('got an unauthorized request, retrying', { error: err.message, type }, correlationId);
191
+ tokens[type][url.origin].accessToken = null;
192
+ return getToken(type, url.origin, correlationId, options)
180
193
  .then((newToken) => {
181
194
  opts.headers.authorization = `Bearer ${newToken}`;
182
195
  return rpRetry(opts)
@@ -202,12 +215,12 @@ const oauthHelper = (config) => {
202
215
  * @requires @mimik/sumologic-winston-logger
203
216
  * @category async
204
217
  * @param {string} method - Method (`GET`, `DELETE`) of the request to be made.
205
- * @param {string} id - `UserId` to associated witht the request.
206
- * @param {UUID<string>} correlationId - CorrelationId to associated with the request.
207
- * @param {object} options - Options to be added to the request. metrics can then be added to the options.
208
- * @return {Promise}.
218
+ * @param {string} id - `UserId` associated with the request.
219
+ * @param {string} correlationId - CorrelationId associated with the request.
220
+ * @param {object} [options] - Options to be added to the request. metrics can then be added to the options.
221
+ * @return {Promise} Resolves with the response from mID.
209
222
  * @fulfil {object} The response of the request made to `mID`.
210
- * @throws {Promise} Will throw a rich error is the request fails or an error if the id is not identified
223
+ * @throws {Error} Will throw a rich error if the request fails or an error if the id is not identified
211
224
  */
212
225
  const authProfile = (method, id, correlationId, options) => {
213
226
  if (!id) return Promise.reject(new Error('Id has to be defined'));
@@ -222,7 +235,7 @@ const oauthHelper = (config) => {
222
235
  if (options && options.metrics) opts.metrics = options.metrics;
223
236
  return rpAuth('mID', opts)
224
237
  .catch((err) => {
225
- const error = getRichError(err.statusCode, 'could perform operation on identity server', { method, id }, err);
238
+ const error = getRichError(err.statusCode, 'could not perform operation on identity server', { method, id }, err);
226
239
 
227
240
  if (error.statusCode === PARAMETER_ERROR && method === 'DELETE') {
228
241
  logger.warn('profile without authprofile', { id, error }, correlationId);
@@ -239,8 +252,3 @@ const oauthHelper = (config) => {
239
252
  };
240
253
 
241
254
  export default oauthHelper;
242
- /**
243
- * This callback is displayed as a global member.
244
- * @callback requestCallback
245
- * @param {object} either `null` or an `error`.
246
- */
package/package.json CHANGED
@@ -1,23 +1,21 @@
1
1
  {
2
2
  "name": "@mimik/oauth-helper",
3
- "version": "4.0.2",
3
+ "version": "4.1.0",
4
4
  "description": "Oauth helper for mimik microservices",
5
5
  "main": "./index.js",
6
6
  "type": "module",
7
+ "exports": "./index.js",
8
+ "engines": {
9
+ "node": ">=24"
10
+ },
7
11
  "scripts": {
8
12
  "lint": "eslint . --no-error-on-unmatched-pattern",
9
13
  "docs": "jsdoc2md index.js > README.md",
10
14
  "test": "mocha --reporter mochawesome --bail --check-leaks test/",
11
- "test-ci": "c8 --reporter=lcov --reporter=text npm test --exit",
15
+ "test-ci": "c8 --reporter=lcov --reporter=text npm test -- --exit",
12
16
  "prepublishOnly": "npm run docs && npm run lint && npm run test-ci",
13
17
  "commit-ready": "npm run docs && npm run lint && npm run test-ci"
14
18
  },
15
- "husky": {
16
- "hooks": {
17
- "pre-commit": "npm run commit-ready",
18
- "pre-push": "npm run test"
19
- }
20
- },
21
19
  "keywords": [
22
20
  "mimik",
23
21
  "microservice"
@@ -29,26 +27,27 @@
29
27
  "url": "https://bitbucket.org/mimiktech/oauth-helper"
30
28
  },
31
29
  "dependencies": {
32
- "@mimik/request-retry": "^4.0.3",
33
- "@mimik/response-helper": "^4.0.4",
34
- "@mimik/sumologic-winston-logger": "^2.0.3",
30
+ "@mimik/request-retry": "^4.0.9",
31
+ "@mimik/response-helper": "^4.0.10",
32
+ "@mimik/sumologic-winston-logger": "^2.1.14",
35
33
  "bluebird": "3.7.2",
36
- "jsonwebtoken": "9.0.2"
34
+ "jsonwebtoken": "9.0.3"
37
35
  },
38
36
  "devDependencies": {
39
- "@eslint/js": "9.31.0",
37
+ "@eslint/js": "9.39.3",
40
38
  "@mimik/eslint-plugin-document-env": "^2.0.8",
41
- "@mimik/request-helper": "2.0.2",
42
- "@stylistic/eslint-plugin": "5.2.1",
43
- "c8": "10.1.3",
44
- "body-parser": "2.2.0",
45
- "chai": "5.2.1",
46
- "eslint": "9.31.0",
39
+ "@mimik/request-helper": "2.0.5",
40
+ "@stylistic/eslint-plugin": "5.9.0",
41
+ "c8": "11.0.0",
42
+ "body-parser": "2.2.2",
43
+ "chai": "6.2.2",
44
+ "eslint": "9.39.3",
47
45
  "eslint-plugin-import": "2.32.0",
48
- "express": "5.1.0",
46
+ "express": "5.2.1",
47
+ "globals": "17.4.0",
49
48
  "husky": "9.1.7",
50
- "jsdoc-to-markdown": "9.1.2",
51
- "mocha": "11.7.1",
52
- "mochawesome": "7.1.3"
49
+ "jsdoc-to-markdown": "9.1.3",
50
+ "mocha": "11.7.5",
51
+ "mochawesome": "7.1.4"
53
52
  }
54
53
  }
package/.husky/pre-commit DELETED
@@ -1 +0,0 @@
1
- npm run commit-ready
package/.husky/pre-push DELETED
@@ -1 +0,0 @@
1
- npm run test
package/.nycrc DELETED
@@ -1,4 +0,0 @@
1
- {
2
- "exclude": ["gulpfile.js"],
3
- "reporter": ["lcov", "text"]
4
- }
package/eslint.config.js DELETED
@@ -1,64 +0,0 @@
1
- import importPlugin from 'eslint-plugin-import';
2
- import js from '@eslint/js';
3
- import processDoc from '@mimik/eslint-plugin-document-env';
4
- import stylistic from '@stylistic/eslint-plugin';
5
-
6
- const MAX_LENGTH_LINE = 180;
7
- const MAX_FUNCTION_PARAMETERS = 6;
8
- const MAX_LINES_IN_FILES = 600;
9
- const MAX_LINES_IN_FUNCTION = 150;
10
- const MAX_STATEMENTS_IN_FUNCTION = 45;
11
- const MIN_KEYS_IN_OBJECT = 10;
12
- const MAX_COMPLEXITY = 30;
13
-
14
- export default [
15
- {
16
- ignores: ['mochawesome-report/**', 'node_modules/**', 'dist/**'],
17
- },
18
- importPlugin.flatConfigs.recommended,
19
- stylistic.configs['recommended-flat'],
20
- js.configs.all,
21
- {
22
- plugins: {
23
- processDoc,
24
- },
25
- languageOptions: {
26
- ecmaVersion: 2022,
27
- globals: {
28
- console: 'readonly',
29
- describe: 'readonly',
30
- it: 'readonly',
31
- require: 'readonly',
32
- },
33
- sourceType: 'module',
34
- },
35
- rules: {
36
- '@stylistic/brace-style': ['warn', 'stroustrup', { allowSingleLine: true }],
37
- '@stylistic/line-comment-position': ['off'],
38
- '@stylistic/semi': ['error', 'always'],
39
- 'capitalized-comments': ['off'],
40
- 'complexity': ['error', MAX_COMPLEXITY],
41
- 'curly': ['off'],
42
- 'id-length': ['error', { exceptions: ['x', 'y', 'z', 'i', 'j', 'k'] }],
43
- 'import/no-extraneous-dependencies': ['error', { devDependencies: true }],
44
- 'import/no-unresolved': ['error', { amd: true, caseSensitiveStrict: true, commonjs: true }],
45
- 'init-declarations': ['off'],
46
- 'linebreak-style': ['off'],
47
- 'max-depth': ['warn', { max: 5 }],
48
- 'max-len': ['warn', MAX_LENGTH_LINE, { ignoreComments: true }],
49
- 'max-lines': ['warn', { max: MAX_LINES_IN_FILES, skipComments: true }],
50
- 'max-lines-per-function': ['warn', { max: MAX_LINES_IN_FUNCTION, skipComments: true }],
51
- 'max-params': ['error', MAX_FUNCTION_PARAMETERS],
52
- 'max-statements': ['warn', MAX_STATEMENTS_IN_FUNCTION],
53
- 'no-confusing-arrow': ['off'], // arrow isnt confusing
54
- 'no-inline-comments': ['off'],
55
- 'no-process-env': ['error'],
56
- 'no-ternary': ['off'],
57
- 'no-undefined': ['off'],
58
- 'one-var': ['error', 'never'],
59
- 'processDoc/validate-document-env': ['error'],
60
- 'quotes': ['warn', 'single'],
61
- 'sort-keys': ['error', 'asc', { caseSensitive: true, minKeys: MIN_KEYS_IN_OBJECT, natural: false }],
62
- },
63
- },
64
- ];
@@ -1,146 +0,0 @@
1
- import './testEnv.js';
2
- import { before, describe, it } from 'mocha';
3
- import { expect, should } from 'chai';
4
- import { config } from './testConfig.js';
5
- import { getCorrelationId } from '@mimik/request-helper';
6
- import { listen } from './serversMock.js';
7
- import oauthHelper from '../index.js';
8
- import { rpRetry } from '@mimik/request-retry';
9
-
10
- should();
11
-
12
- const SYSTEM_ERROR = 500;
13
- const TIMEOUT = 200000;
14
- const DELAY = 100;
15
-
16
- const correlationId = getCorrelationId('--test-OauthHelper--');
17
- // const oauthImplNoGeneric = oauthHelper(config.implNoGeneric);
18
- // const oauthImplGeneric = oauthHelper(config.implGeneric);
19
- const oauthAppGeneric = oauthHelper(config.appGeneric);
20
- const oauthAppUnknownIssuer = oauthHelper(config.appUnknownIssuer);
21
- // const oauthAppExpiredToken = oauthHelper(config.appExpiredToken);
22
- const oauthAppExpiredTokenAndFail = oauthHelper(config.appExpiredTokenAndFail);
23
-
24
- describe('OauthHelper Unit Tests', () => {
25
- before(() => {
26
- listen();
27
- });
28
- describe('rpAuth(type, options)', function Test() {
29
- this.timeout(TIMEOUT);
30
- const requestOptions = {
31
- method: 'GET',
32
- headers: {
33
- 'x-correlation-id': correlationId,
34
- },
35
- uri: 'http://localhost:9070/getTest',
36
- json: true,
37
- };
38
- it('should generate an error rpAuth type non existent', () => oauthAppGeneric.rpAuth(null, requestOptions)
39
- .then(response => expect(response).to.equal('should not return a valid response'))
40
- .catch((err) => {
41
- expect(err.message).to.equal(`rpAuth type non existent for ${requestOptions.method} on ${requestOptions.uri}`);
42
- }));
43
- it('should generate an error used in rpAuth with no dependencies ', () => oauthAppGeneric.rpAuth('unknownDependency', requestOptions)
44
- .then(response => expect(response).to.equal('should not return a valid response'))
45
- .catch((err) => {
46
- expect(err.message).to.equal('type unknownDependency used in rpAuth with no dependencies');
47
- }));
48
- it('should generate an error uri or url non existent', () => {
49
- requestOptions.uri = null;
50
- return oauthAppGeneric.rpAuth('test1', requestOptions)
51
- .then(response => expect(response).to.equal('should not return a valid response'))
52
- .catch((err) => {
53
- expect(err.message).to.equal('uri or url non existent');
54
- });
55
- });
56
- it('should generate an error invalid url address', () => {
57
- requestOptions.uri = 'http//test.com/test';
58
- return oauthAppGeneric.rpAuth('test1', requestOptions)
59
- .then(response => expect(response).to.equal('should not return a valid response'))
60
- .catch((err) => {
61
- expect(err.message).to.include('invalid url address');
62
- });
63
- });
64
- it('should generate an error request error response from token server ', () => {
65
- requestOptions.uri = 'http://localhost:9070/getTest';
66
- return oauthAppUnknownIssuer.rpAuth('test1', requestOptions)
67
- .then(response => expect(response).to.equal('should not return a valid response'))
68
- .catch((err) => {
69
- expect(err.message).to.include('request error response');
70
- });
71
- });
72
- it('should get a response test ok, setting up expiredTokenAndFail ', () => oauthAppExpiredTokenAndFail.rpAuth('test1', requestOptions)
73
- .then((response) => {
74
- expect(response.data).to.equal('test ok');
75
- }));
76
- it('should get a response test ok, using refresh_token and go to client_credentials ', () => oauthAppExpiredTokenAndFail.rpAuth('test1', requestOptions)
77
- .then((response) => {
78
- expect(response.data).to.equal('test ok');
79
- }));
80
- it('should get a response test ok, using refresh_token ', () => oauthAppGeneric.rpAuth('test1', requestOptions)
81
- .then((response) => {
82
- expect(response.data).to.equal('test ok');
83
- }));
84
- it('should get a response test ok, redoing to hit the cache ', () => oauthAppGeneric.rpAuth('test1', requestOptions)
85
- .then((response) => {
86
- expect(response.data).to.equal('test ok');
87
- }));
88
- it('should get a response test ok, after retry ', () => {
89
- const requestOptionsUnAuthorized = {
90
- method: 'GET',
91
- uri: 'http://localhost:9070/GetTestUnAuthorized',
92
- json: true,
93
- };
94
- return oauthAppGeneric.rpAuth('test1', requestOptionsUnAuthorized)
95
- .then((response) => {
96
- expect(response.data).to.equal('test ok');
97
- });
98
- });
99
- it('should get a failure on the target service', () => {
100
- const requestOptionsFailed = {
101
- method: 'GET',
102
- headers: {
103
- 'x-correlation-id': correlationId,
104
- },
105
- uri: 'http://localhost:9070/GetTestFailed',
106
- json: true,
107
- };
108
- return oauthAppGeneric.rpAuth('test1', requestOptionsFailed)
109
- .then(response => expect(response).to.equal('should not return a valid response'))
110
- .catch((err) => {
111
- expect(err.statusCode).to.equal(SYSTEM_ERROR);
112
- });
113
- });
114
- });
115
- describe('authProfile(method, id, correlationId)', function Test() {
116
- this.timeout(TIMEOUT);
117
- it('should generate an error invalid id', () => oauthAppGeneric.authProfile('GET', null, correlationId)
118
- .then(response => expect(response).to.equal('should not return a valid response'))
119
- .catch((err) => {
120
- expect(err.message).to.equal('Id has to be defined');
121
- }));
122
- it('should generate an error on GET', () => oauthAppGeneric.authProfile('GET', '123', correlationId)
123
- .then(response => expect(response).to.equal('should not return a valid response'))
124
- .catch((err) => {
125
- expect(err.message).to.include('could perform operation on identity server');
126
- }));
127
- it('should return nothing', () => oauthAppGeneric.authProfile('DELETE', '123', correlationId)
128
- .then((response) => {
129
- expect(response).to.equal(undefined);
130
- }));
131
- it('should stop mock server', () => rpRetry({
132
- method: 'GET',
133
- headers: {
134
- 'x-correlation-id': correlationId,
135
- },
136
- url: 'http://localhost:9070/stop',
137
- retry: {
138
- delayStrategy: () => DELAY,
139
- retries: 1,
140
- },
141
- })
142
- .catch((err) => {
143
- expect(err.name).to.equal('System');
144
- }));
145
- });
146
- });
@@ -1,135 +0,0 @@
1
- /* eslint-disable no-console */
2
- /* eslint camelcase: ["error", { properties: "never" }] */
3
- import { URL } from 'url';
4
- import bodyParser from 'body-parser';
5
- import { config } from './testConfig.js';
6
- import express from 'express';
7
- import jwt from 'jsonwebtoken';
8
- import process from 'process';
9
- import { setTimeout } from 'timers';
10
-
11
- const TAB = 2;
12
- const OK = 200;
13
- const PARAMETER_ERROR = 400;
14
- const SYSTEM_ERROR = 500;
15
- const FORBIDDEN_ERROR = 403;
16
- const INCR = 1;
17
- const NONE = 0;
18
- const ONE = 1;
19
- const NORMAL_EXIT = 0;
20
- const TIMEOUT = 3000;
21
-
22
- const app = express();
23
- const mockConfig = {
24
- port: 9070,
25
- };
26
- const issuerUrl = new URL(config.appGeneric.security.server.issuer);
27
- const issuerUrlExpiredToken = new URL(config.appExpiredToken.security.server.issuer);
28
- const issuerUrlExpiredTokenAndFail = new URL(config.appExpiredTokenAndFail.security.server.issuer);
29
- const fakeJwt = jwt.sign({}, 'dummy key', { expiresIn: 10000000 });
30
- const fakeExpiredJwt = jwt.sign({}, 'dummy key', { expiresIn: 20 });
31
- let tries = 0;
32
- let expiredTries = 0;
33
-
34
- app.use(bodyParser.json());
35
- app.post(issuerUrl.pathname, (req, res) => {
36
- console.log(`-----> received POST on ${config.appGeneric.security.server.issuer} with body: ${JSON.stringify(req.body, null, TAB)}`);
37
- res.statusCode = OK;
38
- res.send({
39
- data: {
40
- access_token: fakeJwt,
41
- refresh_token: fakeJwt,
42
- },
43
- });
44
- });
45
- app.post(issuerUrlExpiredToken.pathname, (req, res) => {
46
- console.log(`-----> received POST on ${config.appExpiredToken.security.server.issuer} with body: ${JSON.stringify(req.body, null, TAB)}`);
47
- res.statusCode = OK;
48
- res.send({
49
- data: {
50
- access_token: fakeExpiredJwt,
51
- refresh_token: fakeJwt,
52
- },
53
- });
54
- });
55
- app.post(issuerUrlExpiredTokenAndFail.pathname, (req, res) => {
56
- console.log(`-----> received POST on ${config.appExpiredTokenAndFail.security.server.issuer} with body: ${JSON.stringify(req.body, null, TAB)}`);
57
- if (expiredTries === NONE) {
58
- console.log('-----> first POST');
59
- expiredTries += INCR;
60
- res.statusCode = OK;
61
- res.send({
62
- data: {
63
- access_token: fakeExpiredJwt,
64
- refresh_token: fakeJwt,
65
- },
66
- });
67
- }
68
- else if (expiredTries === ONE) {
69
- console.log('-----> second POST');
70
- expiredTries += INCR;
71
- res.statusCode = PARAMETER_ERROR;
72
- res.send({ statusCode: PARAMETER_ERROR });
73
- }
74
- else {
75
- console.log('-----> third POST');
76
- res.statusCode = OK;
77
- res.send({
78
- data: {
79
- access_token: fakeExpiredJwt,
80
- refresh_token: fakeJwt,
81
- },
82
- });
83
- }
84
- });
85
- app.get('/GetTest', (req, res) => {
86
- console.log('-----> received GET');
87
- res.statusCode = OK;
88
- res.send({ data: 'test ok' });
89
- });
90
- app.get('/GetTestUnAuthorized', (req, res) => {
91
- if (tries === NONE) {
92
- console.log('-----> received first GET to be unAuthorized');
93
- tries += INCR;
94
- res.statusCode = FORBIDDEN_ERROR;
95
- res.send({ statusCode: FORBIDDEN_ERROR });
96
- }
97
- else {
98
- console.log('-----> received second GET to be authorized');
99
- res.statusCode = OK;
100
- res.send({ data: 'test ok' });
101
- }
102
- });
103
- app.get('/GetTestFailed', (req, res) => {
104
- console.log('-----> received GET failed');
105
- res.statusCode = SYSTEM_ERROR;
106
- res.send({ statusCode: SYSTEM_ERROR });
107
- });
108
- app.get('/mIDUrl/users/:id', (req, res) => {
109
- console.log('-----> recieved a GET');
110
- res.statusCode = SYSTEM_ERROR;
111
- res.send({ statusCode: SYSTEM_ERROR });
112
- });
113
- app.delete('/mIDUrl/users/:id', (req, res) => {
114
- console.log('-----> received a DELETE');
115
- res.statusCode = PARAMETER_ERROR;
116
- res.send({ statusCode: PARAMETER_ERROR });
117
- });
118
- app.get('/stop', (req, res) => {
119
- console.log('----->', 'Received a stop');
120
- res.statusCode = OK;
121
- res.send({ statusCode: OK });
122
- setTimeout(() => {
123
- process.exit(NORMAL_EXIT);
124
- }, TIMEOUT);
125
- });
126
-
127
- const listen = () => {
128
- app.listen(mockConfig.port, () => {
129
- console.log('----->', `servers mock at ${mockConfig.port}`);
130
- });
131
- };
132
-
133
- export {
134
- listen,
135
- };
@@ -1,212 +0,0 @@
1
- const NO_GENERIC = 'noGeneric';
2
-
3
- const config = {
4
- implImplicit: {
5
- security: {
6
- implicit: {
7
- audience: 'http://implAudience',
8
- issuer: 'http://localhost:9070/implIssuer/oauth/token',
9
- key: 'implKey',
10
- },
11
- },
12
- dependencies: {
13
- mID: {
14
- url: 'http://localhost:9070/mIDUrl',
15
- },
16
- },
17
- },
18
- implNoGeneric: {
19
- security: {
20
- server: {
21
- audience: 'http://implServerAudience',
22
- issuer: 'http://localhost:9070/implServerIssuer/oauth/token',
23
- accessKey: 'implicitAccessKey',
24
- },
25
- generic: {
26
- key: NO_GENERIC,
27
- audience: NO_GENERIC,
28
- },
29
- },
30
- dependencies: {
31
- mID: {
32
- url: 'http://localhost:9070/mIDUrl',
33
- },
34
- },
35
- },
36
- implGeneric: {
37
- security: {
38
- server: {
39
- audience: 'http://implServerAudience',
40
- issuer: 'http://localhost:9070/implServerIssuer/oauth/token',
41
- accessKey: 'implAccessKey',
42
- },
43
- generic: {
44
- audience: 'http://implGenericAudience',
45
- key: 'implGenericKey',
46
- },
47
- },
48
- dependencies: {
49
- mID: {
50
- url: 'http://localhost:9070/mIDUrl',
51
- },
52
- },
53
- },
54
- appNoGeneric: {
55
- server: {
56
- id: 'appServerId',
57
- },
58
- security: {
59
- server: {
60
- audience: 'http://appServerAudience.com',
61
- issuer: 'http://localhost:9070/appNoGenericServerIssuer/oauth/token',
62
- id: 'appServerId',
63
- secret: 'appServerSecret',
64
- accessKey: 'appnAccessKey',
65
- },
66
- generic: {
67
- audience: NO_GENERIC,
68
- key: NO_GENERIC,
69
- },
70
- admin: {
71
- externalId: 'appAdminExternalId',
72
- },
73
- },
74
- dependencies: {
75
- test1: {
76
- audience: 'http://appTest1DependenciesAudience.com',
77
- },
78
- test2: {
79
- audience: 'http://appTest2DependenciesAudience.com',
80
- },
81
- mID: {
82
- url: 'http://localhost:9070/mIDUrl',
83
- },
84
- },
85
- },
86
- appGeneric: {
87
- server: {
88
- id: 'appServerId',
89
- },
90
- security: {
91
- server: {
92
- audience: 'http://appServerAudience',
93
- issuer: 'http://localhost:9070/appGenericServerIssuer/oauth/token',
94
- id: 'appServerId',
95
- secret: 'applServerSecret',
96
- },
97
- generic: {
98
- audience: 'http://appGenericAudience',
99
- key: 'appGenericKey',
100
- },
101
- admin: {
102
- externalId: 'appAdminExternalId',
103
- },
104
- apiKeys: ['12345', '54321'],
105
- },
106
- dependencies: {
107
- test1: {
108
- audience: 'http://appTest1DependenciesAudience',
109
- },
110
- test2: {
111
- audience: 'http://appTest2DependenciesAudience.com',
112
- },
113
- mID: {
114
- url: 'http://localhost:9070/mIDUrl',
115
- },
116
- },
117
- },
118
- appUnknownIssuer: {
119
- server: {
120
- id: 'appServerId',
121
- },
122
- security: {
123
- server: {
124
- issuer: 'http://localhost:9070/unknown/oauth/token',
125
- id: 'appServerId',
126
- secret: 'appServerSecret',
127
- },
128
- generic: {
129
- audience: 'http://appGenericAudience',
130
- key: 'appGenericKey',
131
- },
132
- admin: {
133
- externalId: 'appAdminExternalId',
134
- },
135
- },
136
- dependencies: {
137
- test1: {
138
- audience: 'http://appTest1DependenciesAudience',
139
- },
140
- test2: {
141
- audience: 'http://appTest2DependenciesAudience.com',
142
- },
143
- mID: {
144
- url: 'http://localhost:9070/mIDUrl',
145
- },
146
- },
147
- },
148
- appExpiredToken: {
149
- server: {
150
- id: 'appServerId',
151
- },
152
- security: {
153
- server: {
154
- issuer: 'http://localhost:9070/appGenericServerIssuer/oauth/expiredToken',
155
- id: 'appServerId',
156
- secret: 'appServerSecret',
157
- },
158
- generic: {
159
- audience: 'http://appGenericAudience',
160
- key: 'appGenericKey',
161
- },
162
- admin: {
163
- externalId: 'appAdminExternalId',
164
- },
165
- },
166
- dependencies: {
167
- test1: {
168
- audience: 'http://appTest1DependenciesAudience',
169
- },
170
- test2: {
171
- audience: 'http://appTest2DependenciesAudience.com',
172
- },
173
- mID: {
174
- url: 'http://localhost:9070/mIDUrl',
175
- },
176
- },
177
- },
178
- appExpiredTokenAndFail: {
179
- server: {
180
- id: 'appServerId',
181
- },
182
- security: {
183
- server: {
184
- issuer: 'http://localhost:9070/appGenericServerIssuer/oauth/expiredTokenAndFail',
185
- id: 'appServerId',
186
- secret: 'appServerSecret',
187
- },
188
- generic: {
189
- audience: 'http://appGenericAudience',
190
- key: 'appGenericKey',
191
- },
192
- admin: {
193
- externalId: 'appAdminExternalId',
194
- },
195
- },
196
- dependencies: {
197
- test1: {
198
- audience: 'http://appTest1DependenciesAudience',
199
- },
200
- test2: {
201
- audience: 'http://appTest2DependenciesAudience.com',
202
- },
203
- mID: {
204
- url: 'http://localhost:9070/mIDUrl',
205
- },
206
- },
207
- },
208
- };
209
-
210
- export {
211
- config,
212
- };
package/test/testEnv.js DELETED
@@ -1,20 +0,0 @@
1
- /* eslint no-process-env: "off" */
2
- import process from 'process';
3
-
4
- /**
5
- * The following environment variables are set for the test:
6
- *
7
- * | Env variable name | Description | Default | Comments |
8
- * | ----------------- | ----------- | ------- | -------- |
9
- * | SUMO_LOGIC_ENDPOINT | endpoint to use to log on sumologic | null
10
- * | SUMO_LOGIC_COLLECTOR_CODE | code to use to log on sumologic | null
11
- * | NO_STACK | flag to have a stack associated with the log | yes
12
- * | LOG_LEVEL | log level to log | error
13
- * | CONSOLE_LEVEL | log level to diplay | debug
14
- */
15
-
16
- process.env.SUMO_LOGIC_ENDPOINT = null;
17
- process.env.SUMO_LOGIC_COLLECTOR_CODE = null;
18
- process.env.NO_STACK = 'yes';
19
- process.env.LOG_LEVEL = 'error';
20
- // process.env.CONSOLE_LEVEL = 'debug';