@aloma.io/integration-sdk 3.0.1-1 → 3.0.1-10
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/build/builder/index.d.mts +1 -1
- package/build/builder/index.mjs +15 -11
- package/build/builder/runtime-context.d.mts +1 -1
- package/build/builder/runtime-context.mjs +10 -7
- package/build/builder/transform/index.mjs +18 -18
- package/build/cli.d.mts +1 -0
- package/build/cli.mjs +81 -2
- package/build/controller/index.mjs +5 -5
- package/build/index.d.mts +2 -2
- package/build/index.mjs +2 -2
- package/build/internal/dispatcher/index.cjs +41 -30
- package/build/internal/index.cjs +86 -71
- package/build/internal/util/jwe/cli.cjs +3 -3
- package/build/internal/util/jwe/index.cjs +10 -10
- package/build/internal/websocket/config.cjs +7 -7
- package/build/internal/websocket/connection/constants.cjs +3 -3
- package/build/internal/websocket/connection/index.cjs +9 -9
- package/build/internal/websocket/connection/registration.cjs +7 -7
- package/build/internal/websocket/index.cjs +3 -3
- package/build/internal/websocket/transport/durable.cjs +6 -6
- package/build/internal/websocket/transport/index.cjs +18 -18
- package/build/internal/websocket/transport/packet.cjs +2 -2
- package/build/internal/websocket/transport/processor.cjs +5 -5
- package/package.json +3 -2
- package/src/builder/index.mts +26 -19
- package/src/builder/runtime-context.mts +31 -21
- package/src/builder/transform/index.mts +24 -19
- package/src/cli.mts +107 -0
- package/src/controller/index.mts +13 -7
- package/src/index.mts +2 -2
- package/src/internal/dispatcher/index.cjs +61 -44
- package/src/internal/index.cjs +125 -84
- package/src/internal/util/jwe/cli.cjs +3 -3
- package/src/internal/util/jwe/index.cjs +21 -17
- package/src/internal/websocket/config.cjs +12 -8
- package/src/internal/websocket/connection/constants.cjs +3 -3
- package/src/internal/websocket/connection/index.cjs +11 -11
- package/src/internal/websocket/connection/registration.cjs +9 -9
- package/src/internal/websocket/index.cjs +6 -6
- package/src/internal/websocket/transport/durable.cjs +9 -9
- package/src/internal/websocket/transport/index.cjs +30 -26
- package/src/internal/websocket/transport/packet.cjs +4 -4
- package/src/internal/websocket/transport/processor.cjs +12 -9
- package/template/connector/Containerfile +18 -0
- package/template/connector/entrypoint.sh +5 -0
- package/template/connector/package.json +25 -0
- package/template/connector/src/controller/index.mts +12 -0
- package/template/connector/src/index.mts +6 -0
- package/template/connector/tsconfig.json +27 -0
- package/src/cli.js +0 -1
package/src/internal/index.cjs
CHANGED
@@ -1,44 +1,47 @@
|
|
1
1
|
// @ts-nocheck
|
2
|
-
require(
|
3
|
-
const fs = require(
|
4
|
-
const {Config} = require(
|
5
|
-
const {Connection} = require(
|
6
|
-
const {Transport} = require(
|
7
|
-
const {Dispatcher} = require(
|
8
|
-
const {WebsocketConnector} = require(
|
9
|
-
const JWE = require(
|
10
|
-
const fetch = require(
|
11
|
-
const cuid = require(
|
2
|
+
require("dotenv").config();
|
3
|
+
const fs = require("fs");
|
4
|
+
const { Config } = require("./websocket/config.cjs");
|
5
|
+
const { Connection } = require("./websocket/connection/index.cjs");
|
6
|
+
const { Transport } = require("./websocket/transport/index.cjs");
|
7
|
+
const { Dispatcher } = require("./dispatcher/index.cjs");
|
8
|
+
const { WebsocketConnector } = require("./websocket/index.cjs");
|
9
|
+
const JWE = require("./util/jwe/index.cjs");
|
10
|
+
const fetch = require("node-fetch");
|
11
|
+
const cuid = require("@paralleldrive/cuid2").init({ length: 32 });
|
12
12
|
|
13
13
|
// TODO fetch with retry
|
14
14
|
|
15
15
|
const handlePacketError = (packet, e, transport) => {
|
16
16
|
if (!packet.cb()) {
|
17
|
-
console.dir({msg:
|
17
|
+
console.dir({ msg: "packet error", e, packet }, { depth: null });
|
18
18
|
return;
|
19
19
|
}
|
20
20
|
|
21
|
-
transport.send(transport.newPacket({c: packet.cb(), a: {error:
|
21
|
+
transport.send(transport.newPacket({ c: packet.cb(), a: { error: "" + e } }));
|
22
22
|
};
|
23
23
|
|
24
24
|
const reply = (arg, packet, transport) => {
|
25
25
|
if (!packet.cb()) {
|
26
|
-
console.dir(
|
26
|
+
console.dir(
|
27
|
+
{ msg: "cannot reply to packet without cb", arg, packet },
|
28
|
+
{ depth: null }
|
29
|
+
);
|
27
30
|
return;
|
28
31
|
}
|
29
32
|
|
30
|
-
transport.send(transport.newPacket({c: packet.cb(), a: {...arg}}));
|
33
|
+
transport.send(transport.newPacket({ c: packet.cb(), a: { ...arg } }));
|
31
34
|
};
|
32
35
|
|
33
36
|
const unwrap = async (ret, options) => {
|
34
37
|
if (options?.text) return await ret.text();
|
35
|
-
if (options?.base64) return (await ret.buffer()).toString(
|
38
|
+
if (options?.base64) return (await ret.buffer()).toString("base64");
|
36
39
|
|
37
40
|
return await ret.json();
|
38
41
|
};
|
39
42
|
|
40
43
|
class Fetcher {
|
41
|
-
constructor({retry = 5, baseUrl}) {
|
44
|
+
constructor({ retry = 5, baseUrl }) {
|
42
45
|
this.retry = retry;
|
43
46
|
this.baseUrl = baseUrl;
|
44
47
|
}
|
@@ -66,7 +69,9 @@ class Fetcher {
|
|
66
69
|
if (retries == null) retries = local.retry;
|
67
70
|
|
68
71
|
try {
|
69
|
-
const theURL = `${
|
72
|
+
const theURL = `${
|
73
|
+
baseUrl?.endsWith("/") ? baseUrl : baseUrl + "/"
|
74
|
+
}${url}`.replace(/\/\/+/gi, "/");
|
70
75
|
|
71
76
|
await local.customize(options, args);
|
72
77
|
|
@@ -75,7 +80,7 @@ class Fetcher {
|
|
75
80
|
|
76
81
|
if (status > 399) {
|
77
82
|
const text = await ret.text();
|
78
|
-
const e = new Error(status +
|
83
|
+
const e = new Error(status + " " + text);
|
79
84
|
|
80
85
|
e.status = status;
|
81
86
|
throw e;
|
@@ -95,8 +100,8 @@ class Fetcher {
|
|
95
100
|
}
|
96
101
|
|
97
102
|
class OAuthFetcher extends Fetcher {
|
98
|
-
constructor({oauth, retry = 5, getToken, baseUrl}) {
|
99
|
-
super({retry, baseUrl});
|
103
|
+
constructor({ oauth, retry = 5, getToken, baseUrl }) {
|
104
|
+
super({ retry, baseUrl });
|
100
105
|
|
101
106
|
this.oauth = oauth;
|
102
107
|
this._getToken = getToken;
|
@@ -111,7 +116,8 @@ class OAuthFetcher extends Fetcher {
|
|
111
116
|
if (!force && oauth.accessToken()) return oauth.accessToken();
|
112
117
|
|
113
118
|
const refreshToken = oauth.refreshToken();
|
114
|
-
if (!refreshToken)
|
119
|
+
if (!refreshToken)
|
120
|
+
throw new Error("have no access_token and no refresh_token");
|
115
121
|
|
116
122
|
const ret = await oauth.obtainViaRefreshToken(oauth.refreshToken());
|
117
123
|
|
@@ -120,7 +126,7 @@ class OAuthFetcher extends Fetcher {
|
|
120
126
|
|
121
127
|
return ret.access_token;
|
122
128
|
} else {
|
123
|
-
throw new Error(
|
129
|
+
throw new Error("could not obtain access token via refresh token");
|
124
130
|
}
|
125
131
|
}
|
126
132
|
|
@@ -130,7 +136,11 @@ class OAuthFetcher extends Fetcher {
|
|
130
136
|
return new Promise((resolve, reject) => {
|
131
137
|
setTimeout(async () => {
|
132
138
|
try {
|
133
|
-
resolve(
|
139
|
+
resolve(
|
140
|
+
await local.fetch(url, options, retries, {
|
141
|
+
forceTokenRefresh: e.status === 401,
|
142
|
+
})
|
143
|
+
);
|
134
144
|
} catch (e) {
|
135
145
|
reject(e);
|
136
146
|
}
|
@@ -141,7 +151,7 @@ class OAuthFetcher extends Fetcher {
|
|
141
151
|
async customize(options, args = {}) {
|
142
152
|
const token = await local.getToken(args.forceTokenRefresh);
|
143
153
|
|
144
|
-
options = {...options};
|
154
|
+
options = { ...options };
|
145
155
|
options.headers = {
|
146
156
|
...options.headers,
|
147
157
|
Authorization: `Bearer ${token}`,
|
@@ -180,12 +190,12 @@ class OAuth {
|
|
180
190
|
}
|
181
191
|
|
182
192
|
getClient(arg = {}) {
|
183
|
-
return new OAuthFetcher({...arg, oauth: this});
|
193
|
+
return new OAuthFetcher({ ...arg, oauth: this });
|
184
194
|
}
|
185
195
|
}
|
186
196
|
|
187
197
|
class Connector {
|
188
|
-
constructor({version, id, name}) {
|
198
|
+
constructor({ version, id, name }) {
|
189
199
|
this.id = id;
|
190
200
|
this.version = version;
|
191
201
|
this.name = name;
|
@@ -199,13 +209,13 @@ class Connector {
|
|
199
209
|
var local = this;
|
200
210
|
|
201
211
|
const makeMetrics = () => {
|
202
|
-
const metrics = require(
|
212
|
+
const metrics = require("prom-client");
|
203
213
|
|
204
214
|
const defaultLabels = {
|
205
215
|
service: local.name,
|
206
216
|
connectorId: local.id,
|
207
217
|
connectorVersion: local.version,
|
208
|
-
node: process.env.HOSTNAME ||
|
218
|
+
node: process.env.HOSTNAME || "test",
|
209
219
|
};
|
210
220
|
metrics.register.setDefaultLabels(defaultLabels);
|
211
221
|
metrics.collectDefaultMetrics();
|
@@ -214,11 +224,11 @@ class Connector {
|
|
214
224
|
};
|
215
225
|
|
216
226
|
const makeMetricsServer = (metrics) => {
|
217
|
-
const app = require(
|
227
|
+
const app = require("express")();
|
218
228
|
|
219
|
-
app.get(
|
229
|
+
app.get("/metrics", async (request, response, next) => {
|
220
230
|
response.status(200);
|
221
|
-
response.set(
|
231
|
+
response.set("Content-type", metrics.contentType);
|
222
232
|
response.send(await metrics.register.metrics());
|
223
233
|
response.end();
|
224
234
|
});
|
@@ -226,17 +236,19 @@ class Connector {
|
|
226
236
|
return app;
|
227
237
|
};
|
228
238
|
|
229
|
-
makeMetricsServer(makeMetrics()).listen(4050,
|
239
|
+
makeMetricsServer(makeMetrics()).listen(4050, "0.0.0.0");
|
230
240
|
|
231
|
-
const {processPacket, start, introspect, configSchema} =
|
241
|
+
const { processPacket, start, introspect, configSchema } =
|
242
|
+
this.dispatcher.build();
|
232
243
|
|
233
244
|
const config = new Config({
|
234
245
|
id: this.id,
|
235
246
|
version: this.version,
|
236
247
|
name: process.env.HOSTNAME || this.name,
|
237
248
|
registrationToken: process.env.REGISTRATION_TOKEN,
|
238
|
-
endpoint: process.env.DEVICE_ENDPOINT ||
|
239
|
-
wsEndpoint:
|
249
|
+
endpoint: process.env.DEVICE_ENDPOINT || "https://connect.aloma.io/",
|
250
|
+
wsEndpoint:
|
251
|
+
process.env.WEBSOCKET_ENDPOINT || "wss://transport.aloma.io/transport/",
|
240
252
|
privateKey: process.env.PRIVATE_KEY,
|
241
253
|
publicKey: process.env.PUBLIC_KEY,
|
242
254
|
introspect,
|
@@ -249,16 +261,16 @@ class Connector {
|
|
249
261
|
} catch (e) {
|
250
262
|
const haveKey = !!process.env.PRIVATE_KEY;
|
251
263
|
const jwe = new JWE({});
|
252
|
-
var text =
|
264
|
+
var text = "Please double check the env variables";
|
253
265
|
|
254
266
|
if (!haveKey) {
|
255
267
|
await jwe.newPair();
|
256
268
|
text =
|
257
|
-
|
269
|
+
"fresh keys generated, set environment variables: \n\nPRIVATE_KEY: " +
|
258
270
|
(await jwe.exportPrivateAsBase64()) +
|
259
|
-
|
271
|
+
"\n\nPUBLIC_KEY: " +
|
260
272
|
(await jwe.exportPublicAsBase64()) +
|
261
|
-
|
273
|
+
"\n";
|
262
274
|
}
|
263
275
|
|
264
276
|
console.log(`
|
@@ -281,7 +293,7 @@ ${text}
|
|
281
293
|
const fields = configSchema().fields;
|
282
294
|
|
283
295
|
const keys = Object.keys(secrets);
|
284
|
-
const jwe = await config.validateKeys(
|
296
|
+
const jwe = await config.validateKeys("RSA-OAEP-256");
|
285
297
|
|
286
298
|
for (var i = 0; i < keys.length; ++i) {
|
287
299
|
const key = keys[i];
|
@@ -294,18 +306,25 @@ ${text}
|
|
294
306
|
try {
|
295
307
|
decrypted[key] = await jwe.decrypt(value, config.id());
|
296
308
|
} catch (e) {
|
297
|
-
console.log(
|
309
|
+
console.log("failed to decrypt key", key, config.id(), e);
|
298
310
|
}
|
299
311
|
}
|
300
312
|
}
|
301
313
|
|
302
314
|
this.startOAuth = async function (args) {
|
303
|
-
if (!this._oauth) throw new Error(
|
304
|
-
|
305
|
-
const clientId =
|
306
|
-
|
307
|
-
|
308
|
-
|
315
|
+
if (!this._oauth) throw new Error("oauth not configured");
|
316
|
+
|
317
|
+
const clientId =
|
318
|
+
this._oauth.clientId ||
|
319
|
+
process.env.OAUTH_CLIENT_ID ||
|
320
|
+
decrypted.clientId;
|
321
|
+
if (!clientId) throw new Error("clientId not configured");
|
322
|
+
|
323
|
+
const scopes =
|
324
|
+
this._oauth.scope ||
|
325
|
+
process.env.OAUTH_SCOPE ||
|
326
|
+
decrypted.scope ||
|
327
|
+
"";
|
309
328
|
const useCodeChallenge = !!that._oauth.useCodeChallenge;
|
310
329
|
|
311
330
|
return {
|
@@ -319,20 +338,27 @@ ${text}
|
|
319
338
|
this.finishOAuth = async function (arg) {
|
320
339
|
var that = this;
|
321
340
|
|
322
|
-
if (!this._oauth) throw new Error(
|
323
|
-
if (!this._oauth.tokenURL && !this._oauth.finishOAuth)
|
341
|
+
if (!this._oauth) throw new Error("oauth not configured");
|
342
|
+
if (!this._oauth.tokenURL && !this._oauth.finishOAuth)
|
343
|
+
throw new Error("need tokenURL or finishOAuth(arg)");
|
324
344
|
|
325
345
|
var data = null;
|
326
346
|
|
327
347
|
const doFinish = async () => {
|
328
|
-
if (!arg.code || !arg.redirectURI)
|
348
|
+
if (!arg.code || !arg.redirectURI)
|
349
|
+
throw new Error("need code and redirectUri");
|
329
350
|
|
330
|
-
const clientId =
|
331
|
-
|
351
|
+
const clientId =
|
352
|
+
that._oauth.clientId ||
|
353
|
+
process.env.OAUTH_CLIENT_ID ||
|
354
|
+
decrypted.clientId;
|
355
|
+
if (!clientId) throw new Error("clientId not configured");
|
332
356
|
|
333
357
|
const clientSecret =
|
334
|
-
that._oauth.clientSecret ||
|
335
|
-
|
358
|
+
that._oauth.clientSecret ||
|
359
|
+
process.env.OAUTH_CLIENT_SECRET ||
|
360
|
+
decrypted.clientSecret;
|
361
|
+
if (!clientSecret) throw new Error("clientSecret not configured");
|
336
362
|
|
337
363
|
const additionalTokenArgs = that._oauth.additionalTokenArgs || {};
|
338
364
|
const useAuthHeader = !!that._oauth.useAuthHeader;
|
@@ -349,8 +375,9 @@ ${text}
|
|
349
375
|
}
|
350
376
|
|
351
377
|
let headers = {
|
352
|
-
|
353
|
-
|
378
|
+
"Content-Type":
|
379
|
+
"application/x-www-form-urlencoded;charset=UTF-8",
|
380
|
+
Accept: "application/json",
|
354
381
|
};
|
355
382
|
|
356
383
|
if (useAuthHeader) {
|
@@ -367,7 +394,7 @@ ${text}
|
|
367
394
|
}
|
368
395
|
|
369
396
|
const response = await fetch(that._oauth.tokenURL, {
|
370
|
-
method:
|
397
|
+
method: "POST",
|
371
398
|
body: new URLSearchParams(body),
|
372
399
|
headers,
|
373
400
|
});
|
@@ -378,14 +405,18 @@ ${text}
|
|
378
405
|
if (status === 200) {
|
379
406
|
const ret = JSON.parse(text);
|
380
407
|
if (ret.error) {
|
381
|
-
throw new Error(
|
408
|
+
throw new Error(
|
409
|
+
`${status} ${ret.error} ${ret.error_description || ""}`
|
410
|
+
);
|
382
411
|
} else if (ret.access_token) {
|
383
|
-
return {...ret};
|
412
|
+
return { ...ret };
|
384
413
|
} else {
|
385
|
-
throw new Error(
|
414
|
+
throw new Error(
|
415
|
+
status + " response has no access_token - " + text
|
416
|
+
);
|
386
417
|
}
|
387
418
|
} else {
|
388
|
-
throw new Error(status +
|
419
|
+
throw new Error(status + " " + text);
|
389
420
|
}
|
390
421
|
};
|
391
422
|
|
@@ -399,18 +430,18 @@ ${text}
|
|
399
430
|
data = await doFinish();
|
400
431
|
}
|
401
432
|
|
402
|
-
const jwe = await config.validateKeys(
|
433
|
+
const jwe = await config.validateKeys("RSA-OAEP-256");
|
403
434
|
|
404
|
-
return {value: await jwe.encrypt(data,
|
435
|
+
return { value: await jwe.encrypt(data, "none", config.id()) };
|
405
436
|
};
|
406
437
|
|
407
438
|
const saveOAuthResult = async (what) => {
|
408
|
-
const jwe = await config.validateKeys(
|
439
|
+
const jwe = await config.validateKeys("RSA-OAEP-256");
|
409
440
|
const packet = transport.newPacket({});
|
410
441
|
|
411
|
-
packet.method(
|
442
|
+
packet.method("connector.config-update");
|
412
443
|
packet.args({
|
413
|
-
value: await jwe.encrypt(what,
|
444
|
+
value: await jwe.encrypt(what, "none", config.id()),
|
414
445
|
});
|
415
446
|
|
416
447
|
transport.send(packet);
|
@@ -419,11 +450,17 @@ ${text}
|
|
419
450
|
const that = this;
|
420
451
|
|
421
452
|
const getRefreshToken = async (refreshToken) => {
|
422
|
-
const clientId =
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
if (!
|
453
|
+
const clientId =
|
454
|
+
that._oauth.clientId ||
|
455
|
+
process.env.OAUTH_CLIENT_ID ||
|
456
|
+
decrypted.clientId;
|
457
|
+
if (!clientId) throw new Error("clientId not configured");
|
458
|
+
|
459
|
+
const clientSecret =
|
460
|
+
that._oauth.clientSecret ||
|
461
|
+
process.env.OAUTH_CLIENT_SECRET ||
|
462
|
+
decrypted.clientSecret;
|
463
|
+
if (!clientSecret) throw new Error("clientSecret not configured");
|
427
464
|
|
428
465
|
const useAuthHeader = !!that._oauth.useAuthHeader;
|
429
466
|
|
@@ -437,16 +474,17 @@ ${text}
|
|
437
474
|
}
|
438
475
|
|
439
476
|
const response = await fetch(that._oauth.tokenURL, {
|
440
|
-
method:
|
477
|
+
method: "POST",
|
441
478
|
body: new URLSearchParams({
|
442
|
-
grant_type:
|
479
|
+
grant_type: "refresh_token",
|
443
480
|
refresh_token: refreshToken,
|
444
481
|
client_id: clientId,
|
445
482
|
client_secret: clientSecret,
|
446
483
|
}),
|
447
484
|
headers: {
|
448
|
-
|
449
|
-
|
485
|
+
"Content-Type":
|
486
|
+
"application/x-www-form-urlencoded;charset=UTF-8",
|
487
|
+
Accept: "application/json",
|
450
488
|
...headers,
|
451
489
|
},
|
452
490
|
});
|
@@ -457,7 +495,9 @@ ${text}
|
|
457
495
|
if (status === 200) {
|
458
496
|
return JSON.parse(text);
|
459
497
|
} else {
|
460
|
-
throw new Error(
|
498
|
+
throw new Error(
|
499
|
+
"could not get refresh token " + status + " " + text
|
500
|
+
);
|
461
501
|
}
|
462
502
|
};
|
463
503
|
|
@@ -467,7 +507,8 @@ ${text}
|
|
467
507
|
start({
|
468
508
|
config: decrypted,
|
469
509
|
oauth: theOAuth,
|
470
|
-
getClient: (arg) =>
|
510
|
+
getClient: (arg) =>
|
511
|
+
theOAuth ? theOAuth.getClient(arg) : new Fetcher({ ...arg }),
|
471
512
|
newTask: (name, data) => {
|
472
513
|
return new Promise((resolve, reject) => {
|
473
514
|
const packet = transport.newPacket(
|
@@ -476,7 +517,7 @@ ${text}
|
|
476
517
|
`_req-${cuid()}`
|
477
518
|
);
|
478
519
|
|
479
|
-
packet.method(
|
520
|
+
packet.method("connector.task.new");
|
480
521
|
packet.args({
|
481
522
|
name,
|
482
523
|
a: data,
|
@@ -493,7 +534,7 @@ ${text}
|
|
493
534
|
`_req-${cuid()}`
|
494
535
|
);
|
495
536
|
|
496
|
-
packet.method(
|
537
|
+
packet.method("connector.task.update");
|
497
538
|
packet.args({
|
498
539
|
id,
|
499
540
|
a: data,
|
@@ -529,19 +570,19 @@ ${text}
|
|
529
570
|
process.exit(0);
|
530
571
|
};
|
531
572
|
|
532
|
-
process.on(
|
573
|
+
process.on("uncaughtException", (e) => {
|
533
574
|
console.log(e);
|
534
575
|
});
|
535
576
|
|
536
|
-
process.on(
|
577
|
+
process.on("unhandledRejection", (e) => {
|
537
578
|
console.log(e);
|
538
579
|
});
|
539
580
|
|
540
|
-
process.on(
|
541
|
-
process.on(
|
581
|
+
process.on("SIGTERM", term);
|
582
|
+
process.on("SIGINT", term);
|
542
583
|
|
543
584
|
await server.start();
|
544
585
|
}
|
545
586
|
}
|
546
587
|
|
547
|
-
module.exports = {Connector};
|
588
|
+
module.exports = { Connector };
|
@@ -1,12 +1,12 @@
|
|
1
|
-
const JWE = require(
|
1
|
+
const JWE = require("./index");
|
2
2
|
|
3
3
|
const main = async () => {
|
4
4
|
const jwe = new JWE({});
|
5
5
|
await jwe.newPair();
|
6
6
|
|
7
|
-
console.log(
|
7
|
+
console.log("private key");
|
8
8
|
console.log(await jwe.exportPrivateAsBase64());
|
9
|
-
console.log(
|
9
|
+
console.log("public key");
|
10
10
|
console.log(await jwe.exportPublicAsBase64());
|
11
11
|
};
|
12
12
|
|
@@ -1,8 +1,8 @@
|
|
1
|
-
const jose = require(
|
1
|
+
const jose = require("jose");
|
2
2
|
|
3
3
|
class JWE {
|
4
|
-
constructor({algorithm =
|
5
|
-
this.issuer =
|
4
|
+
constructor({ algorithm = "PS256" }) {
|
5
|
+
this.issuer = "home.aloma.io";
|
6
6
|
this.algorithm = algorithm;
|
7
7
|
}
|
8
8
|
|
@@ -20,47 +20,51 @@ class JWE {
|
|
20
20
|
async exportPrivateAsBase64() {
|
21
21
|
const pair = await this.exportPair();
|
22
22
|
|
23
|
-
return Buffer.from(pair.privateKey).toString(
|
23
|
+
return Buffer.from(pair.privateKey).toString("base64");
|
24
24
|
}
|
25
25
|
|
26
26
|
async exportPublicAsBase64() {
|
27
27
|
const pair = await this.exportPair();
|
28
28
|
|
29
|
-
return Buffer.from(pair.publicKey).toString(
|
29
|
+
return Buffer.from(pair.publicKey).toString("base64");
|
30
30
|
}
|
31
31
|
|
32
|
-
async importPair({publicKey, privateKey, algorithm}) {
|
32
|
+
async importPair({ publicKey, privateKey, algorithm }) {
|
33
33
|
this.pair = {
|
34
34
|
publicKey: await jose.importSPKI(publicKey, algorithm),
|
35
35
|
privateKey: await jose.importPKCS8(privateKey, algorithm),
|
36
36
|
};
|
37
37
|
}
|
38
38
|
|
39
|
-
async importBase64Pair({publicKey, privateKey, algorithm}) {
|
39
|
+
async importBase64Pair({ publicKey, privateKey, algorithm }) {
|
40
40
|
this.importPair({
|
41
|
-
publicKey: Buffer.from(publicKey,
|
42
|
-
privateKey: Buffer.from(privateKey,
|
41
|
+
publicKey: Buffer.from(publicKey, "base64").toString(),
|
42
|
+
privateKey: Buffer.from(privateKey, "base64").toString(),
|
43
43
|
algorithm,
|
44
44
|
});
|
45
45
|
}
|
46
46
|
|
47
|
-
async encrypt(what, expiration =
|
48
|
-
const item = new jose.EncryptJWT({_data: {...what}})
|
49
|
-
.setProtectedHeader({alg: algorithm, enc:
|
47
|
+
async encrypt(what, expiration = "7d", audience, algorithm = "RSA-OAEP-256") {
|
48
|
+
const item = new jose.EncryptJWT({ _data: { ...what } })
|
49
|
+
.setProtectedHeader({ alg: algorithm, enc: "A256GCM" })
|
50
50
|
.setIssuedAt()
|
51
51
|
.setIssuer(this.issuer)
|
52
52
|
.setAudience(audience);
|
53
53
|
|
54
|
-
if (expiration && expiration !==
|
54
|
+
if (expiration && expiration !== "none") item.setExpirationTime(expiration);
|
55
55
|
|
56
56
|
return await item.encrypt(this.pair.publicKey);
|
57
57
|
}
|
58
58
|
|
59
59
|
async decrypt(what, audience) {
|
60
|
-
const {payload, protectedHeader} = await jose.jwtDecrypt(
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
const { payload, protectedHeader } = await jose.jwtDecrypt(
|
61
|
+
what,
|
62
|
+
this.pair.privateKey,
|
63
|
+
{
|
64
|
+
issuer: this.issuer,
|
65
|
+
audience,
|
66
|
+
}
|
67
|
+
);
|
64
68
|
|
65
69
|
return payload._data;
|
66
70
|
}
|
@@ -1,5 +1,5 @@
|
|
1
|
-
const C = require(
|
2
|
-
const JWE = require(
|
1
|
+
const C = require("./connection/constants.cjs");
|
2
|
+
const JWE = require("../util/jwe/index.cjs");
|
3
3
|
|
4
4
|
class Config {
|
5
5
|
constructor({
|
@@ -28,15 +28,19 @@ class Config {
|
|
28
28
|
this._introspect = introspect;
|
29
29
|
this._configSchema = configSchema;
|
30
30
|
|
31
|
-
if (!registrationToken)
|
32
|
-
|
33
|
-
if (!
|
31
|
+
if (!registrationToken)
|
32
|
+
throw new Error("empty registration token (set env.REGISTRATION_TOKEN)");
|
33
|
+
if (!endpoint) throw new Error("empty endpoint (set env.DEVICE_ENDPOINT)");
|
34
|
+
if (!wsEndpoint)
|
35
|
+
throw new Error("empty registration token (set env.WEBSOCKET_ENDPOINT)");
|
34
36
|
|
35
|
-
if (!this._id || !this._version)
|
37
|
+
if (!this._id || !this._version)
|
38
|
+
throw new Error("need connector id and version");
|
36
39
|
}
|
37
40
|
|
38
41
|
async validateKeys(algorithm) {
|
39
|
-
if (!this._privateKey || !this._publicKey)
|
42
|
+
if (!this._privateKey || !this._publicKey)
|
43
|
+
throw new Error("need private and public key");
|
40
44
|
|
41
45
|
await this._jwe.importBase64Pair({
|
42
46
|
publicKey: this._publicKey,
|
@@ -100,4 +104,4 @@ class Config {
|
|
100
104
|
}
|
101
105
|
}
|
102
106
|
|
103
|
-
module.exports = {Config};
|
107
|
+
module.exports = { Config };
|
@@ -1,10 +1,10 @@
|
|
1
|
-
const AUTHORIZATION =
|
1
|
+
const AUTHORIZATION = "Authorization";
|
2
2
|
|
3
3
|
module.exports = {
|
4
4
|
augmentRequest: (what, config) => {
|
5
5
|
what.headers = {
|
6
6
|
...what.headers,
|
7
|
-
|
7
|
+
"User-Agent": config.id() + "/" + config.version(),
|
8
8
|
};
|
9
9
|
|
10
10
|
what.headers[AUTHORIZATION] = `Connector ${config.token()}`;
|
@@ -15,7 +15,7 @@ module.exports = {
|
|
15
15
|
augmentRegistration: (what, config) => {
|
16
16
|
what.headers = {
|
17
17
|
...what.headers,
|
18
|
-
|
18
|
+
"User-Agent": config.id() + "/" + config.version(),
|
19
19
|
};
|
20
20
|
|
21
21
|
what.headers[AUTHORIZATION] = `Connector ${config.registrationToken()}`;
|