@openfin/cloud-interop-core-api 0.0.1-alpha.37c2746 → 0.0.1-alpha.37e6bd5
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 +2 -2
- package/bundle.d.ts +11 -12
- package/index.cjs +14 -107
- package/index.mjs +14 -107
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# @openfin/cloud-interop-core-api
|
|
2
2
|
|
|
3
|
-
This package contains the core interop library that handles all interactions with the
|
|
3
|
+
This package contains the core interop library that handles all interactions with the Here™ Cloud Interop Service.
|
|
4
4
|
|
|
5
5
|
It is callable via browser or node applications.
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
## Authentication
|
|
9
9
|
|
|
10
|
-
The library supports authentication with the
|
|
10
|
+
The library supports authentication with the Here™ Cloud Interop Service using the following methods:
|
|
11
11
|
- Basic Authentication
|
|
12
12
|
- JWT Token Authentication
|
|
13
13
|
- Default Authentication i.e. Interactive session based authentication using cookies
|
package/bundle.d.ts
CHANGED
|
@@ -245,36 +245,36 @@ export declare class CloudInteropAPI {
|
|
|
245
245
|
/**
|
|
246
246
|
* Connects and creates a session on the Cloud Interop service
|
|
247
247
|
*
|
|
248
|
-
* @param parameters - The parameters to use to connect
|
|
249
|
-
* @returns Promise
|
|
248
|
+
* @param {ConnectParameters} parameters - The parameters to use to connect
|
|
249
|
+
* @returns {*} {Promise<void>}
|
|
250
250
|
* @memberof CloudInteropAPI
|
|
251
|
-
* @throws CloudInteropAPIError - If an error occurs during connection
|
|
252
|
-
* @throws AuthorizationError - If the connection is unauthorized
|
|
251
|
+
* @throws {CloudInteropAPIError} - If an error occurs during connection
|
|
252
|
+
* @throws {AuthorizationError} - If the connection is unauthorized
|
|
253
253
|
*/
|
|
254
254
|
connect(parameters: ConnectParameters): Promise<void>;
|
|
255
255
|
/**
|
|
256
256
|
* Disconnects from the Cloud Interop service
|
|
257
257
|
*
|
|
258
|
-
* @returns Promise
|
|
258
|
+
* @returns {*} {Promise<void>}
|
|
259
259
|
* @memberof CloudInteropAPI
|
|
260
|
-
* @throws CloudInteropAPIError - If an error occurs during disconnection
|
|
260
|
+
* @throws {CloudInteropAPIError} - If an error occurs during disconnection
|
|
261
261
|
*/
|
|
262
262
|
disconnect(): Promise<void>;
|
|
263
263
|
/**
|
|
264
264
|
* Publishes a new context for the given context group to the other connected sessions
|
|
265
265
|
*
|
|
266
|
-
* @param contextGroup - The context group to publish to
|
|
267
|
-
* @param context - The context to publish
|
|
268
|
-
* @returns Promise
|
|
266
|
+
* @param {string} contextGroup - The context group to publish to
|
|
267
|
+
* @param {object} context - The context to publish
|
|
268
|
+
* @returns {*} {Promise<void>}
|
|
269
269
|
* @memberof CloudInteropAPI
|
|
270
270
|
*/
|
|
271
271
|
setContext(contextGroup: string, context: InferredContext): Promise<void>;
|
|
272
272
|
/**
|
|
273
273
|
* Starts an intent discovery operation
|
|
274
274
|
*
|
|
275
|
-
* @returns Promise
|
|
275
|
+
* @returns {*} {Promise<void>}
|
|
276
276
|
* @memberof CloudInteropAPI
|
|
277
|
-
* @throws CloudInteropAPIError - If an error occurs during intent discovery
|
|
277
|
+
* @throws {CloudInteropAPIError} - If an error occurs during intent discovery
|
|
278
278
|
*/
|
|
279
279
|
startIntentDiscovery(options: StartIntentDiscoveryOptions): Promise<void>;
|
|
280
280
|
raiseIntent(options: RaiseIntentAPIOptions): Promise<void>;
|
|
@@ -418,7 +418,6 @@ export declare type CreateSessionResponse = {
|
|
|
418
418
|
sub: string;
|
|
419
419
|
platformId: string;
|
|
420
420
|
sourceId: string;
|
|
421
|
-
localSessionExpiryHandling?: boolean;
|
|
422
421
|
};
|
|
423
422
|
|
|
424
423
|
declare const errorSchema: z.ZodObject<{
|
package/index.cjs
CHANGED
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
var buffer = require('buffer');
|
|
4
4
|
var mqtt = require('mqtt');
|
|
5
5
|
|
|
6
|
-
var l=t=>{let e=t.replaceAll("-","+").replaceAll("_","/");return e.padEnd(e.length+(4-e.length%4)%4,"=")};
|
|
7
|
-
|
|
8
6
|
class CloudInteropAPIError extends Error {
|
|
9
7
|
code;
|
|
10
8
|
constructor(message = 'An unexpected error has occurred', code = 'UNEXPECTED_ERROR', cause) {
|
|
@@ -355,7 +353,6 @@ class CloudInteropAPI {
|
|
|
355
353
|
#attemptingToReconnect = false;
|
|
356
354
|
#events = new EventController();
|
|
357
355
|
#intents;
|
|
358
|
-
#sessionTimer;
|
|
359
356
|
constructor(cloudInteropSettings) {
|
|
360
357
|
this.#cloudInteropSettings = cloudInteropSettings;
|
|
361
358
|
}
|
|
@@ -368,11 +365,11 @@ class CloudInteropAPI {
|
|
|
368
365
|
/**
|
|
369
366
|
* Connects and creates a session on the Cloud Interop service
|
|
370
367
|
*
|
|
371
|
-
* @param parameters - The parameters to use to connect
|
|
372
|
-
* @returns Promise
|
|
368
|
+
* @param {ConnectParameters} parameters - The parameters to use to connect
|
|
369
|
+
* @returns {*} {Promise<void>}
|
|
373
370
|
* @memberof CloudInteropAPI
|
|
374
|
-
* @throws CloudInteropAPIError - If an error occurs during connection
|
|
375
|
-
* @throws AuthorizationError - If the connection is unauthorized
|
|
371
|
+
* @throws {CloudInteropAPIError} - If an error occurs during connection
|
|
372
|
+
* @throws {AuthorizationError} - If the connection is unauthorized
|
|
376
373
|
*/
|
|
377
374
|
async connect(parameters) {
|
|
378
375
|
this.#validateConnectParams(parameters);
|
|
@@ -396,11 +393,6 @@ class CloudInteropAPI {
|
|
|
396
393
|
throw new CloudInteropAPIError(`Failed to connect to the Cloud Interop service: ${this.#cloudInteropSettings.url}`, 'ERR_CONNECT', new Error(createSessionResponse.statusText));
|
|
397
394
|
}
|
|
398
395
|
this.#sessionDetails = (await createSessionResponse.json());
|
|
399
|
-
// If local session expiry handling is enabled, start the session timer
|
|
400
|
-
if (this.#sessionDetails.localSessionExpiryHandling) {
|
|
401
|
-
this.#logger('debug', `Local session expiry handling is enabled`);
|
|
402
|
-
this.#startSessionTimer();
|
|
403
|
-
}
|
|
404
396
|
const sessionRootTopic = this.#sessionDetails.sessionRootTopic;
|
|
405
397
|
const clientOptions = {
|
|
406
398
|
keepalive: this.#keepAliveIntervalSeconds,
|
|
@@ -430,7 +422,9 @@ class CloudInteropAPI {
|
|
|
430
422
|
if (error instanceof mqtt.ErrorWithReasonCode) {
|
|
431
423
|
switch (error.code) {
|
|
432
424
|
case BadUserNamePasswordError: {
|
|
433
|
-
this.#
|
|
425
|
+
await this.#disconnect(false);
|
|
426
|
+
this.#logger('warn', `Session expired`);
|
|
427
|
+
this.#events.emitEvent('session-expired');
|
|
434
428
|
return;
|
|
435
429
|
}
|
|
436
430
|
default: {
|
|
@@ -484,9 +478,9 @@ class CloudInteropAPI {
|
|
|
484
478
|
/**
|
|
485
479
|
* Disconnects from the Cloud Interop service
|
|
486
480
|
*
|
|
487
|
-
* @returns Promise
|
|
481
|
+
* @returns {*} {Promise<void>}
|
|
488
482
|
* @memberof CloudInteropAPI
|
|
489
|
-
* @throws CloudInteropAPIError - If an error occurs during disconnection
|
|
483
|
+
* @throws {CloudInteropAPIError} - If an error occurs during disconnection
|
|
490
484
|
*/
|
|
491
485
|
async disconnect() {
|
|
492
486
|
await this.#disconnect(true);
|
|
@@ -494,9 +488,9 @@ class CloudInteropAPI {
|
|
|
494
488
|
/**
|
|
495
489
|
* Publishes a new context for the given context group to the other connected sessions
|
|
496
490
|
*
|
|
497
|
-
* @param contextGroup - The context group to publish to
|
|
498
|
-
* @param context - The context to publish
|
|
499
|
-
* @returns Promise
|
|
491
|
+
* @param {string} contextGroup - The context group to publish to
|
|
492
|
+
* @param {object} context - The context to publish
|
|
493
|
+
* @returns {*} {Promise<void>}
|
|
500
494
|
* @memberof CloudInteropAPI
|
|
501
495
|
*/
|
|
502
496
|
async setContext(contextGroup, context) {
|
|
@@ -523,9 +517,9 @@ class CloudInteropAPI {
|
|
|
523
517
|
/**
|
|
524
518
|
* Starts an intent discovery operation
|
|
525
519
|
*
|
|
526
|
-
* @returns Promise
|
|
520
|
+
* @returns {*} {Promise<void>}
|
|
527
521
|
* @memberof CloudInteropAPI
|
|
528
|
-
* @throws CloudInteropAPIError - If an error occurs during intent discovery
|
|
522
|
+
* @throws {CloudInteropAPIError} - If an error occurs during intent discovery
|
|
529
523
|
*/
|
|
530
524
|
async startIntentDiscovery(options) {
|
|
531
525
|
this.#throwIfNotConnected();
|
|
@@ -566,11 +560,6 @@ class CloudInteropAPI {
|
|
|
566
560
|
if (!this.#connectionParams) {
|
|
567
561
|
throw new Error('Connect parameters must be provided');
|
|
568
562
|
}
|
|
569
|
-
// Cancel session timer if it's running
|
|
570
|
-
if (this.#sessionTimer) {
|
|
571
|
-
clearTimeout(this.#sessionTimer);
|
|
572
|
-
this.#sessionTimer = undefined;
|
|
573
|
-
}
|
|
574
563
|
const disconnectResponse = await fetch(`${this.#cloudInteropSettings.url}/api/sessions/${this.#sessionDetails.sessionId}`, {
|
|
575
564
|
method: 'DELETE',
|
|
576
565
|
headers: getRequestHeaders(this.#connectionParams),
|
|
@@ -669,88 +658,6 @@ class CloudInteropAPI {
|
|
|
669
658
|
throw new Error('MQTT client not connected');
|
|
670
659
|
}
|
|
671
660
|
}
|
|
672
|
-
/**
|
|
673
|
-
* Extracts the expiration timestamp from a JWT token.
|
|
674
|
-
*
|
|
675
|
-
* @param token - The JWT token string
|
|
676
|
-
* @returns The expiration timestamp in seconds, or null if extraction fails
|
|
677
|
-
*/
|
|
678
|
-
#extractExpirationFromJwt(token) {
|
|
679
|
-
try {
|
|
680
|
-
// JWT tokens have three parts separated by dots: header.payload.signature
|
|
681
|
-
// The exp claim is in the payload
|
|
682
|
-
const parts = token.split('.');
|
|
683
|
-
if (parts.length < 2) {
|
|
684
|
-
this.#logger('warn', 'Invalid JWT token format: expected at least 2 parts');
|
|
685
|
-
return null;
|
|
686
|
-
}
|
|
687
|
-
const payload = parts[1];
|
|
688
|
-
// Decode base64url encoded payload
|
|
689
|
-
const decodedBytes = buffer.Buffer.from(l(payload), 'base64');
|
|
690
|
-
const payloadJson = decodedBytes.toString('utf8');
|
|
691
|
-
// Parse JSON to get the exp claim
|
|
692
|
-
const claims = JSON.parse(payloadJson);
|
|
693
|
-
const exp = claims.exp;
|
|
694
|
-
if (exp === undefined || exp === null) {
|
|
695
|
-
this.#logger('warn', "JWT token does not contain 'exp' claim");
|
|
696
|
-
return null;
|
|
697
|
-
}
|
|
698
|
-
if (typeof exp !== 'number') {
|
|
699
|
-
this.#logger('warn', `JWT token 'exp' claim is not a number: ${exp}`);
|
|
700
|
-
return null;
|
|
701
|
-
}
|
|
702
|
-
return exp;
|
|
703
|
-
}
|
|
704
|
-
catch (error) {
|
|
705
|
-
this.#logger('error', `Failed to extract expiration from JWT token: ${error instanceof Error ? error.message : error}`);
|
|
706
|
-
return null;
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
/**
|
|
710
|
-
* Start a session timer that will expire at the time specified in the JWT token's exp claim.
|
|
711
|
-
* When the timer fires, it executes the same actions as the BadUserNamePasswordError case.
|
|
712
|
-
*/
|
|
713
|
-
#startSessionTimer() {
|
|
714
|
-
if (!this.#sessionDetails?.localSessionExpiryHandling) {
|
|
715
|
-
return;
|
|
716
|
-
}
|
|
717
|
-
const token = this.#sessionDetails.token;
|
|
718
|
-
if (!token) {
|
|
719
|
-
this.#logger('warn', 'Cannot start session timer: token not available');
|
|
720
|
-
return;
|
|
721
|
-
}
|
|
722
|
-
// Extract expiration time from JWT token
|
|
723
|
-
const expTimestamp = this.#extractExpirationFromJwt(token);
|
|
724
|
-
if (expTimestamp === null) {
|
|
725
|
-
this.#logger('warn', 'Cannot start session timer: could not extract expiration from JWT token');
|
|
726
|
-
return;
|
|
727
|
-
}
|
|
728
|
-
const currentTimeSeconds = Math.floor(Date.now() / 1000);
|
|
729
|
-
const delaySeconds = expTimestamp - currentTimeSeconds;
|
|
730
|
-
if (delaySeconds <= 0) {
|
|
731
|
-
this.#logger('warn', 'JWT token has already expired or expires immediately');
|
|
732
|
-
// Execute the same actions as BadUserNamePasswordError case
|
|
733
|
-
this.#handleSessionExpiry();
|
|
734
|
-
return;
|
|
735
|
-
}
|
|
736
|
-
// Clear any existing timer
|
|
737
|
-
if (this.#sessionTimer) {
|
|
738
|
-
clearTimeout(this.#sessionTimer);
|
|
739
|
-
}
|
|
740
|
-
const expirationTimeString = new Date(expTimestamp * 1000).toISOString();
|
|
741
|
-
this.#logger('debug', `Starting session timer to expire in ${delaySeconds} seconds (at ${expirationTimeString})`);
|
|
742
|
-
this.#sessionTimer = setTimeout(async () => {
|
|
743
|
-
this.#handleSessionExpiry();
|
|
744
|
-
}, delaySeconds * 1000);
|
|
745
|
-
}
|
|
746
|
-
/**
|
|
747
|
-
* Handles session expiry by executing the same actions as the BadUserNamePasswordError case.
|
|
748
|
-
*/
|
|
749
|
-
async #handleSessionExpiry() {
|
|
750
|
-
await this.#disconnect(false);
|
|
751
|
-
this.#logger('warn', 'Session expired');
|
|
752
|
-
this.#events.emitEvent('session-expired');
|
|
753
|
-
}
|
|
754
661
|
}
|
|
755
662
|
|
|
756
663
|
exports.AuthorizationError = AuthorizationError;
|
package/index.mjs
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Buffer } from 'buffer';
|
|
2
2
|
import mqtt from 'mqtt';
|
|
3
3
|
|
|
4
|
-
var l=t=>{let e=t.replaceAll("-","+").replaceAll("_","/");return e.padEnd(e.length+(4-e.length%4)%4,"=")};
|
|
5
|
-
|
|
6
4
|
class CloudInteropAPIError extends Error {
|
|
7
5
|
code;
|
|
8
6
|
constructor(message = 'An unexpected error has occurred', code = 'UNEXPECTED_ERROR', cause) {
|
|
@@ -353,7 +351,6 @@ class CloudInteropAPI {
|
|
|
353
351
|
#attemptingToReconnect = false;
|
|
354
352
|
#events = new EventController();
|
|
355
353
|
#intents;
|
|
356
|
-
#sessionTimer;
|
|
357
354
|
constructor(cloudInteropSettings) {
|
|
358
355
|
this.#cloudInteropSettings = cloudInteropSettings;
|
|
359
356
|
}
|
|
@@ -366,11 +363,11 @@ class CloudInteropAPI {
|
|
|
366
363
|
/**
|
|
367
364
|
* Connects and creates a session on the Cloud Interop service
|
|
368
365
|
*
|
|
369
|
-
* @param parameters - The parameters to use to connect
|
|
370
|
-
* @returns Promise
|
|
366
|
+
* @param {ConnectParameters} parameters - The parameters to use to connect
|
|
367
|
+
* @returns {*} {Promise<void>}
|
|
371
368
|
* @memberof CloudInteropAPI
|
|
372
|
-
* @throws CloudInteropAPIError - If an error occurs during connection
|
|
373
|
-
* @throws AuthorizationError - If the connection is unauthorized
|
|
369
|
+
* @throws {CloudInteropAPIError} - If an error occurs during connection
|
|
370
|
+
* @throws {AuthorizationError} - If the connection is unauthorized
|
|
374
371
|
*/
|
|
375
372
|
async connect(parameters) {
|
|
376
373
|
this.#validateConnectParams(parameters);
|
|
@@ -394,11 +391,6 @@ class CloudInteropAPI {
|
|
|
394
391
|
throw new CloudInteropAPIError(`Failed to connect to the Cloud Interop service: ${this.#cloudInteropSettings.url}`, 'ERR_CONNECT', new Error(createSessionResponse.statusText));
|
|
395
392
|
}
|
|
396
393
|
this.#sessionDetails = (await createSessionResponse.json());
|
|
397
|
-
// If local session expiry handling is enabled, start the session timer
|
|
398
|
-
if (this.#sessionDetails.localSessionExpiryHandling) {
|
|
399
|
-
this.#logger('debug', `Local session expiry handling is enabled`);
|
|
400
|
-
this.#startSessionTimer();
|
|
401
|
-
}
|
|
402
394
|
const sessionRootTopic = this.#sessionDetails.sessionRootTopic;
|
|
403
395
|
const clientOptions = {
|
|
404
396
|
keepalive: this.#keepAliveIntervalSeconds,
|
|
@@ -428,7 +420,9 @@ class CloudInteropAPI {
|
|
|
428
420
|
if (error instanceof mqtt.ErrorWithReasonCode) {
|
|
429
421
|
switch (error.code) {
|
|
430
422
|
case BadUserNamePasswordError: {
|
|
431
|
-
this.#
|
|
423
|
+
await this.#disconnect(false);
|
|
424
|
+
this.#logger('warn', `Session expired`);
|
|
425
|
+
this.#events.emitEvent('session-expired');
|
|
432
426
|
return;
|
|
433
427
|
}
|
|
434
428
|
default: {
|
|
@@ -482,9 +476,9 @@ class CloudInteropAPI {
|
|
|
482
476
|
/**
|
|
483
477
|
* Disconnects from the Cloud Interop service
|
|
484
478
|
*
|
|
485
|
-
* @returns Promise
|
|
479
|
+
* @returns {*} {Promise<void>}
|
|
486
480
|
* @memberof CloudInteropAPI
|
|
487
|
-
* @throws CloudInteropAPIError - If an error occurs during disconnection
|
|
481
|
+
* @throws {CloudInteropAPIError} - If an error occurs during disconnection
|
|
488
482
|
*/
|
|
489
483
|
async disconnect() {
|
|
490
484
|
await this.#disconnect(true);
|
|
@@ -492,9 +486,9 @@ class CloudInteropAPI {
|
|
|
492
486
|
/**
|
|
493
487
|
* Publishes a new context for the given context group to the other connected sessions
|
|
494
488
|
*
|
|
495
|
-
* @param contextGroup - The context group to publish to
|
|
496
|
-
* @param context - The context to publish
|
|
497
|
-
* @returns Promise
|
|
489
|
+
* @param {string} contextGroup - The context group to publish to
|
|
490
|
+
* @param {object} context - The context to publish
|
|
491
|
+
* @returns {*} {Promise<void>}
|
|
498
492
|
* @memberof CloudInteropAPI
|
|
499
493
|
*/
|
|
500
494
|
async setContext(contextGroup, context) {
|
|
@@ -521,9 +515,9 @@ class CloudInteropAPI {
|
|
|
521
515
|
/**
|
|
522
516
|
* Starts an intent discovery operation
|
|
523
517
|
*
|
|
524
|
-
* @returns Promise
|
|
518
|
+
* @returns {*} {Promise<void>}
|
|
525
519
|
* @memberof CloudInteropAPI
|
|
526
|
-
* @throws CloudInteropAPIError - If an error occurs during intent discovery
|
|
520
|
+
* @throws {CloudInteropAPIError} - If an error occurs during intent discovery
|
|
527
521
|
*/
|
|
528
522
|
async startIntentDiscovery(options) {
|
|
529
523
|
this.#throwIfNotConnected();
|
|
@@ -564,11 +558,6 @@ class CloudInteropAPI {
|
|
|
564
558
|
if (!this.#connectionParams) {
|
|
565
559
|
throw new Error('Connect parameters must be provided');
|
|
566
560
|
}
|
|
567
|
-
// Cancel session timer if it's running
|
|
568
|
-
if (this.#sessionTimer) {
|
|
569
|
-
clearTimeout(this.#sessionTimer);
|
|
570
|
-
this.#sessionTimer = undefined;
|
|
571
|
-
}
|
|
572
561
|
const disconnectResponse = await fetch(`${this.#cloudInteropSettings.url}/api/sessions/${this.#sessionDetails.sessionId}`, {
|
|
573
562
|
method: 'DELETE',
|
|
574
563
|
headers: getRequestHeaders(this.#connectionParams),
|
|
@@ -667,88 +656,6 @@ class CloudInteropAPI {
|
|
|
667
656
|
throw new Error('MQTT client not connected');
|
|
668
657
|
}
|
|
669
658
|
}
|
|
670
|
-
/**
|
|
671
|
-
* Extracts the expiration timestamp from a JWT token.
|
|
672
|
-
*
|
|
673
|
-
* @param token - The JWT token string
|
|
674
|
-
* @returns The expiration timestamp in seconds, or null if extraction fails
|
|
675
|
-
*/
|
|
676
|
-
#extractExpirationFromJwt(token) {
|
|
677
|
-
try {
|
|
678
|
-
// JWT tokens have three parts separated by dots: header.payload.signature
|
|
679
|
-
// The exp claim is in the payload
|
|
680
|
-
const parts = token.split('.');
|
|
681
|
-
if (parts.length < 2) {
|
|
682
|
-
this.#logger('warn', 'Invalid JWT token format: expected at least 2 parts');
|
|
683
|
-
return null;
|
|
684
|
-
}
|
|
685
|
-
const payload = parts[1];
|
|
686
|
-
// Decode base64url encoded payload
|
|
687
|
-
const decodedBytes = Buffer.from(l(payload), 'base64');
|
|
688
|
-
const payloadJson = decodedBytes.toString('utf8');
|
|
689
|
-
// Parse JSON to get the exp claim
|
|
690
|
-
const claims = JSON.parse(payloadJson);
|
|
691
|
-
const exp = claims.exp;
|
|
692
|
-
if (exp === undefined || exp === null) {
|
|
693
|
-
this.#logger('warn', "JWT token does not contain 'exp' claim");
|
|
694
|
-
return null;
|
|
695
|
-
}
|
|
696
|
-
if (typeof exp !== 'number') {
|
|
697
|
-
this.#logger('warn', `JWT token 'exp' claim is not a number: ${exp}`);
|
|
698
|
-
return null;
|
|
699
|
-
}
|
|
700
|
-
return exp;
|
|
701
|
-
}
|
|
702
|
-
catch (error) {
|
|
703
|
-
this.#logger('error', `Failed to extract expiration from JWT token: ${error instanceof Error ? error.message : error}`);
|
|
704
|
-
return null;
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
/**
|
|
708
|
-
* Start a session timer that will expire at the time specified in the JWT token's exp claim.
|
|
709
|
-
* When the timer fires, it executes the same actions as the BadUserNamePasswordError case.
|
|
710
|
-
*/
|
|
711
|
-
#startSessionTimer() {
|
|
712
|
-
if (!this.#sessionDetails?.localSessionExpiryHandling) {
|
|
713
|
-
return;
|
|
714
|
-
}
|
|
715
|
-
const token = this.#sessionDetails.token;
|
|
716
|
-
if (!token) {
|
|
717
|
-
this.#logger('warn', 'Cannot start session timer: token not available');
|
|
718
|
-
return;
|
|
719
|
-
}
|
|
720
|
-
// Extract expiration time from JWT token
|
|
721
|
-
const expTimestamp = this.#extractExpirationFromJwt(token);
|
|
722
|
-
if (expTimestamp === null) {
|
|
723
|
-
this.#logger('warn', 'Cannot start session timer: could not extract expiration from JWT token');
|
|
724
|
-
return;
|
|
725
|
-
}
|
|
726
|
-
const currentTimeSeconds = Math.floor(Date.now() / 1000);
|
|
727
|
-
const delaySeconds = expTimestamp - currentTimeSeconds;
|
|
728
|
-
if (delaySeconds <= 0) {
|
|
729
|
-
this.#logger('warn', 'JWT token has already expired or expires immediately');
|
|
730
|
-
// Execute the same actions as BadUserNamePasswordError case
|
|
731
|
-
this.#handleSessionExpiry();
|
|
732
|
-
return;
|
|
733
|
-
}
|
|
734
|
-
// Clear any existing timer
|
|
735
|
-
if (this.#sessionTimer) {
|
|
736
|
-
clearTimeout(this.#sessionTimer);
|
|
737
|
-
}
|
|
738
|
-
const expirationTimeString = new Date(expTimestamp * 1000).toISOString();
|
|
739
|
-
this.#logger('debug', `Starting session timer to expire in ${delaySeconds} seconds (at ${expirationTimeString})`);
|
|
740
|
-
this.#sessionTimer = setTimeout(async () => {
|
|
741
|
-
this.#handleSessionExpiry();
|
|
742
|
-
}, delaySeconds * 1000);
|
|
743
|
-
}
|
|
744
|
-
/**
|
|
745
|
-
* Handles session expiry by executing the same actions as the BadUserNamePasswordError case.
|
|
746
|
-
*/
|
|
747
|
-
async #handleSessionExpiry() {
|
|
748
|
-
await this.#disconnect(false);
|
|
749
|
-
this.#logger('warn', 'Session expired');
|
|
750
|
-
this.#events.emitEvent('session-expired');
|
|
751
|
-
}
|
|
752
659
|
}
|
|
753
660
|
|
|
754
661
|
export { AuthorizationError, CloudInteropAPI, CloudInteropAPIError };
|