@nsshunt/stsutils 1.3.25 → 1.5.1
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/authutils.js +193 -5
- package/package.json +11 -10
- package/stsutils.js +1 -3
- package/log.js +0 -33
- package/network.js +0 -37
package/authutils.js
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
|
+
const debug = require('debug')(`stsutils`);
|
|
1
2
|
const jwt = require('jsonwebtoken');
|
|
2
3
|
const { status } = require('./status');
|
|
3
4
|
const fs = require('fs');
|
|
4
5
|
const goptions = require('@nsshunt/stsconfig').$options;
|
|
6
|
+
const tough = require('tough-cookie');
|
|
7
|
+
const Cookie = tough.Cookie;
|
|
8
|
+
const cookiejar = new tough.CookieJar();
|
|
9
|
+
const colors = require('colors');
|
|
10
|
+
const axios = require('axios');
|
|
11
|
+
const http = require('http');
|
|
5
12
|
|
|
6
13
|
class AuthUtils
|
|
7
14
|
{
|
|
8
15
|
#privateKey = null;
|
|
9
16
|
#publicKey = null;
|
|
17
|
+
#httpAgent = null;
|
|
10
18
|
|
|
11
19
|
constructor()
|
|
12
20
|
{
|
|
@@ -14,20 +22,25 @@ class AuthUtils
|
|
|
14
22
|
// http://travistidwell.com/jsencrypt/demo/
|
|
15
23
|
// https://www.csfieldguide.org.nz/en/interactives/rsa-key-generator/
|
|
16
24
|
// https://jwt.io/
|
|
17
|
-
|
|
18
|
-
// This code is for development / non-prod purposes only.
|
|
19
|
-
// For production, the keys to come from a secrets store.
|
|
20
|
-
this.#privateKey = fs.readFileSync(goptions.asprivatekeypath, 'utf8');
|
|
21
|
-
this.#publicKey = fs.readFileSync(goptions.aspublickeypath, 'utf8');
|
|
22
25
|
}
|
|
23
26
|
|
|
27
|
+
// This code is for development / non-prod purposes only.
|
|
28
|
+
// For production, the keys to come from a secrets store.
|
|
24
29
|
get privateKey()
|
|
25
30
|
{
|
|
31
|
+
if (this.#privateKey === null) {
|
|
32
|
+
this.#privateKey = fs.readFileSync(goptions.asprivatekeypath, 'utf8');
|
|
33
|
+
}
|
|
26
34
|
return this.#privateKey;
|
|
27
35
|
}
|
|
28
36
|
|
|
37
|
+
// This code is for development / non-prod purposes only.
|
|
38
|
+
// For production, the keys to come from a secrets store.
|
|
29
39
|
get publicKey()
|
|
30
40
|
{
|
|
41
|
+
if (this.#publicKey === null) {
|
|
42
|
+
this.#publicKey = fs.readFileSync(goptions.aspublickeypath, 'utf8');
|
|
43
|
+
}
|
|
31
44
|
return this.#publicKey;
|
|
32
45
|
}
|
|
33
46
|
|
|
@@ -105,6 +118,181 @@ class AuthUtils
|
|
|
105
118
|
}
|
|
106
119
|
}
|
|
107
120
|
}
|
|
121
|
+
|
|
122
|
+
#GetDurationColour(duration)
|
|
123
|
+
{
|
|
124
|
+
if (duration > 250) {
|
|
125
|
+
return colors.red;
|
|
126
|
+
} else if (duration > 150) {
|
|
127
|
+
return colors.magenta;
|
|
128
|
+
} else if (duration > 50) {
|
|
129
|
+
return colors.blue;
|
|
130
|
+
} else if (duration > 10) {
|
|
131
|
+
return colors.green;
|
|
132
|
+
} else {
|
|
133
|
+
return colors.black;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
LoginBrowser = async (options) => {
|
|
138
|
+
const { authendpoint, authUserName, authUserEMail, authUserPassword, defaultTimeout, publishDebug } = options;
|
|
139
|
+
try {
|
|
140
|
+
let processStart = performance.now();
|
|
141
|
+
let duration = 0;
|
|
142
|
+
let accessToken = null;
|
|
143
|
+
let payload = { name: authUserName, password: authUserPassword, email: authUserEMail }
|
|
144
|
+
let retVal = await axios({
|
|
145
|
+
url: `${authendpoint}/login`
|
|
146
|
+
,method: 'post'
|
|
147
|
+
,data: payload
|
|
148
|
+
,timeout: defaultTimeout
|
|
149
|
+
});
|
|
150
|
+
duration = (performance.now() - processStart).toFixed(4);
|
|
151
|
+
if (publishDebug) debug(this.#GetDurationColour(duration)(`AuthUtils.LoginBrowser request duration: [${duration}]`));
|
|
152
|
+
accessToken = retVal.data.detail.token;
|
|
153
|
+
return {
|
|
154
|
+
accessToken: accessToken,
|
|
155
|
+
duration: duration
|
|
156
|
+
}
|
|
157
|
+
} catch (error) {
|
|
158
|
+
if (publishDebug) debug(`Error (AuthUtils:LoginBrowser): ${error}`.red);
|
|
159
|
+
throw error;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// https://stackoverflow.com/questions/43002444/make-axios-send-cookies-in-its-requests-automatically
|
|
164
|
+
// axios.get('some api url', {withCredentials: true});
|
|
165
|
+
// https://medium.com/@adityasrivast/handling-cookies-with-axios-872790241a9b
|
|
166
|
+
// https://www.codegrepper.com/code-examples/javascript/axios+send+cookies
|
|
167
|
+
// http only cookies
|
|
168
|
+
RefreshAuthTokenBrowser = async (options) => {
|
|
169
|
+
const { authendpoint, defaultTimeout, publishDebug } = options;
|
|
170
|
+
try {
|
|
171
|
+
let processStart = performance.now();
|
|
172
|
+
let duration = 0;
|
|
173
|
+
let accessToken = null;
|
|
174
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
|
|
175
|
+
// https://stackoverflow.com/questions/43002444/make-axios-send-cookies-in-its-requests-automatically
|
|
176
|
+
// axios.get('some api url', {withCredentials: true});
|
|
177
|
+
let retVal = await axios({
|
|
178
|
+
url: `${authendpoint}/refreshtoken`
|
|
179
|
+
,method: 'post'
|
|
180
|
+
,timeout: defaultTimeout
|
|
181
|
+
,withCredentials: true
|
|
182
|
+
});
|
|
183
|
+
duration = (performance.now() - processStart).toFixed(4);
|
|
184
|
+
if (publishDebug) debug(this.#GetDurationColour(duration)(`AuthUtils.RefreshAuthTokenBrowser request duration: [${duration}]`));
|
|
185
|
+
accessToken = retVal.data.detail.token;
|
|
186
|
+
return {
|
|
187
|
+
accessToken: accessToken,
|
|
188
|
+
duration: duration
|
|
189
|
+
}
|
|
190
|
+
} catch (error) {
|
|
191
|
+
if (publishDebug) debug(`Error (AuthUtils:RefreshAuthTokenBrowser): ${error}`.red);
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
#setCookiesToJar = (authendpoint, headers) =>
|
|
197
|
+
{
|
|
198
|
+
let cookies = null;
|
|
199
|
+
if (headers['set-cookie'] instanceof Array)
|
|
200
|
+
cookies = headers['set-cookie'].map(Cookie.parse);
|
|
201
|
+
else
|
|
202
|
+
cookies = [Cookie.parse(headers['set-cookie'])];
|
|
203
|
+
|
|
204
|
+
return cookiejar.setCookie(cookies[0], `${authendpoint}`);
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
#getCookiesFromJar = (authendpoint) =>
|
|
208
|
+
{
|
|
209
|
+
return cookiejar.getCookies(`${authendpoint}`);
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
#getHttpAgent = () =>
|
|
213
|
+
{
|
|
214
|
+
if (this.#httpAgent === null) {
|
|
215
|
+
// https://nodejs.org/api/http.html#class-httpagent
|
|
216
|
+
this.#httpAgent = new http.Agent({
|
|
217
|
+
keepAlive: true,
|
|
218
|
+
maxSockets: 10,
|
|
219
|
+
maxTotalSockets: 10,
|
|
220
|
+
maxFreeSockets: 10,
|
|
221
|
+
timeout: 5000
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
return this.#httpAgent;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
LoginNode = async (options) =>
|
|
228
|
+
{
|
|
229
|
+
const { authendpoint, authUserName, authUserEMail, authUserPassword, defaultTimeout, publishDebug } = options;
|
|
230
|
+
try {
|
|
231
|
+
let processStart = performance.now();
|
|
232
|
+
let duration = 0;
|
|
233
|
+
let accessToken = null;
|
|
234
|
+
let payload = { name: authUserName, password: authUserPassword, email: authUserEMail }
|
|
235
|
+
let retVal = await axios({
|
|
236
|
+
url: `${authendpoint}/login`
|
|
237
|
+
,method: 'post'
|
|
238
|
+
,data: payload
|
|
239
|
+
,timeout: defaultTimeout
|
|
240
|
+
,httpAgent: this.#getHttpAgent()
|
|
241
|
+
// Use below if using a socket endpoint
|
|
242
|
+
//,socketPath: '/var/run/sts/stsrest01.sock'
|
|
243
|
+
});
|
|
244
|
+
duration = (performance.now() - processStart).toFixed(4);
|
|
245
|
+
if (publishDebug) debug(this.#GetDurationColour(duration)(`AuthUtils.LoginNode request duration: [${duration}]`));
|
|
246
|
+
accessToken = retVal.data.detail.token;
|
|
247
|
+
await this.#setCookiesToJar(authendpoint, retVal.headers);
|
|
248
|
+
return {
|
|
249
|
+
accessToken: accessToken,
|
|
250
|
+
duration: duration
|
|
251
|
+
}
|
|
252
|
+
} catch (error)
|
|
253
|
+
{
|
|
254
|
+
if (publishDebug) debug(`Error (AuthUtils:LoginNode): ${error}`.red);
|
|
255
|
+
throw error;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// https://stackoverflow.com/questions/43002444/make-axios-send-cookies-in-its-requests-automatically
|
|
260
|
+
// axios.get('some api url', {withCredentials: true});
|
|
261
|
+
// https://medium.com/@adityasrivast/handling-cookies-with-axios-872790241a9b
|
|
262
|
+
// https://www.codegrepper.com/code-examples/javascript/axios+send+cookies
|
|
263
|
+
// http only cookies
|
|
264
|
+
RefreshAuthTokenNode = async (options) =>
|
|
265
|
+
{
|
|
266
|
+
const { authendpoint, defaultTimeout, publishDebug } = options;
|
|
267
|
+
try {
|
|
268
|
+
let processStart = performance.now();
|
|
269
|
+
let duration = 0;
|
|
270
|
+
let accessToken = null;
|
|
271
|
+
let cookies = await this.#getCookiesFromJar(authendpoint);
|
|
272
|
+
let retVal = await axios({
|
|
273
|
+
url: `${authendpoint}/refreshtoken`
|
|
274
|
+
,method: 'post'
|
|
275
|
+
,headers: {
|
|
276
|
+
Cookie: cookies
|
|
277
|
+
}
|
|
278
|
+
,timeout: defaultTimeout
|
|
279
|
+
,httpAgent: this.#httpAgent,
|
|
280
|
+
// Use below for socket connections
|
|
281
|
+
//,socketPath: '/var/run/sts/stsrest01.sock'
|
|
282
|
+
});
|
|
283
|
+
duration = (performance.now() - processStart).toFixed(4);
|
|
284
|
+
if (publishDebug) debug(this.#GetDurationColour(duration)(`AuthUtils.RefreshAuthTokenBrowser request duration: [${duration}]`));
|
|
285
|
+
accessToken = retVal.data.detail.token;
|
|
286
|
+
await this.#setCookiesToJar(authendpoint, retVal.headers);
|
|
287
|
+
return {
|
|
288
|
+
accessToken: accessToken,
|
|
289
|
+
duration: duration
|
|
290
|
+
}
|
|
291
|
+
} catch (error) {
|
|
292
|
+
if (publishDebug) debug(`Error (AuthUtils:RefreshAuthTokenBrowser): ${error}`.red);
|
|
293
|
+
throw error;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
108
296
|
}
|
|
109
297
|
|
|
110
298
|
module.exports = { AuthUtils };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nsshunt/stsutils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "stsutils.js",
|
|
6
6
|
"scripts": {
|
|
@@ -22,18 +22,19 @@
|
|
|
22
22
|
"parser": "@babel/eslint-parser"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@babel/core": "^7.16.
|
|
26
|
-
"@babel/eslint-parser": "^7.16.
|
|
27
|
-
"@babel/plugin-proposal-class-properties": "^7.16.
|
|
28
|
-
"@babel/plugin-proposal-private-methods": "^7.16.
|
|
29
|
-
"eslint": "^8.
|
|
30
|
-
"jest": "^27.
|
|
25
|
+
"@babel/core": "^7.16.5",
|
|
26
|
+
"@babel/eslint-parser": "^7.16.5",
|
|
27
|
+
"@babel/plugin-proposal-class-properties": "^7.16.5",
|
|
28
|
+
"@babel/plugin-proposal-private-methods": "^7.16.5",
|
|
29
|
+
"eslint": "^8.4.1",
|
|
30
|
+
"jest": "^27.4.5"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@nsshunt/stsconfig": "^1.
|
|
33
|
+
"@nsshunt/stsconfig": "^1.4.0",
|
|
34
34
|
"colors": "^1.4.0",
|
|
35
|
-
"debug": "^4.3.
|
|
35
|
+
"debug": "^4.3.3",
|
|
36
36
|
"express": "^4.17.1",
|
|
37
|
-
"jsonwebtoken": "^8.5.1"
|
|
37
|
+
"jsonwebtoken": "^8.5.1",
|
|
38
|
+
"tough-cookie": "^4.0.0"
|
|
38
39
|
}
|
|
39
40
|
}
|
package/stsutils.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
let sleep = require('./sleep.js');
|
|
2
2
|
let status = require('./status.js');
|
|
3
|
-
let network = require('./network.js');
|
|
4
3
|
let authutils = require('./authutils.js');
|
|
5
4
|
let stsoptionsbase = require('./stsoptionsbase.js');
|
|
6
5
|
let stsrouterbase = require('./stsrouterbase.js');
|
|
7
|
-
let log = require('./log.js');
|
|
8
6
|
|
|
9
|
-
module.exports = { sleep, status,
|
|
7
|
+
module.exports = { sleep, status, authutils, stsoptionsbase, stsrouterbase };
|
package/log.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
const cluster = require('cluster');
|
|
2
|
-
const colors = require('colors');
|
|
3
|
-
const debug = require('debug')(`proc:${process.pid}`);
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Default styles :-
|
|
7
|
-
* Worker messages - green
|
|
8
|
-
* Master messages - cyan + bold
|
|
9
|
-
* IPC Messages - grey. The message command itself will be bold.
|
|
10
|
-
* Signals - yellow (e.g. SIGINT or SIGTERM etc.
|
|
11
|
-
* @param {*} instruments
|
|
12
|
-
* @returns
|
|
13
|
-
*/
|
|
14
|
-
module.exports = (appName, instruments) =>
|
|
15
|
-
{
|
|
16
|
-
return (msg) =>
|
|
17
|
-
{
|
|
18
|
-
let prefix = '';
|
|
19
|
-
let col = null;
|
|
20
|
-
|
|
21
|
-
if (cluster.isMaster)
|
|
22
|
-
{
|
|
23
|
-
prefix = 'M';
|
|
24
|
-
col = colors.bold.cyan;
|
|
25
|
-
} else {
|
|
26
|
-
prefix = 'W';
|
|
27
|
-
col = colors.green;
|
|
28
|
-
}
|
|
29
|
-
let msgEx = col(`${prefix}(${process.pid}) [${appName}]: ${msg}`);
|
|
30
|
-
debug(msgEx);
|
|
31
|
-
instruments.logger.LogMessage(msgEx);
|
|
32
|
-
};
|
|
33
|
-
};
|
package/network.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
const os = require('os');
|
|
2
|
-
|
|
3
|
-
const GetNetworkInterfaces = () =>
|
|
4
|
-
{
|
|
5
|
-
const nets = os.networkInterfaces();
|
|
6
|
-
let results = { };
|
|
7
|
-
for (const name of Object.keys(nets)) {
|
|
8
|
-
for (const net of nets[name]) {
|
|
9
|
-
// Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses
|
|
10
|
-
if (net.family === 'IPv4' && !net.internal) {
|
|
11
|
-
if (!results[name]) {
|
|
12
|
-
results[name] = [];
|
|
13
|
-
}
|
|
14
|
-
results[name].push(net.address);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
return results;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const GetFirstNetworkInterface = () =>
|
|
22
|
-
{
|
|
23
|
-
let nics = GetNetworkInterfaces();
|
|
24
|
-
let hostaddr = null;
|
|
25
|
-
for (let nic in nics)
|
|
26
|
-
{
|
|
27
|
-
let val = nics[nic];
|
|
28
|
-
if (val.length > 0)
|
|
29
|
-
{
|
|
30
|
-
hostaddr = val[0];
|
|
31
|
-
break;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return hostaddr;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
module.exports = { GetNetworkInterfaces, GetFirstNetworkInterface }
|