astro-tokenkit 1.0.18 → 1.0.20
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 +14 -0
- package/dist/auth/manager.d.ts +1 -1
- package/dist/auth/manager.js +45 -18
- package/dist/client/client.js +12 -6
- package/dist/index.cjs +77 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +77 -33
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +65 -27
- package/dist/middleware.cjs.map +1 -1
- package/dist/middleware.js +65 -27
- package/dist/middleware.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/utils/fetch.js +20 -9
- package/package.json +4 -2
package/dist/middleware.cjs
CHANGED
|
@@ -370,6 +370,7 @@ function isExpired(expiresAt, now, policy = {}) {
|
|
|
370
370
|
}
|
|
371
371
|
|
|
372
372
|
// packages/astro-tokenkit/src/utils/fetch.ts
|
|
373
|
+
let sharedInsecureAgent = null;
|
|
373
374
|
/**
|
|
374
375
|
* Perform a fetch request with optional certificate validation bypass
|
|
375
376
|
*/
|
|
@@ -378,16 +379,26 @@ function safeFetch(url, init, config) {
|
|
|
378
379
|
const fetchFn = config.fetch || fetch;
|
|
379
380
|
const fetchOptions = Object.assign({}, init);
|
|
380
381
|
if (config.dangerouslyIgnoreCertificateErrors && typeof process !== 'undefined') {
|
|
381
|
-
// In Node.js environment
|
|
382
382
|
try {
|
|
383
|
-
// Try to use undici Agent if available
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
383
|
+
// Try to use undici Agent if available to avoid global process.env changes
|
|
384
|
+
if (!sharedInsecureAgent) {
|
|
385
|
+
// @ts-ignore
|
|
386
|
+
const undici = yield import('undici').catch(() => null);
|
|
387
|
+
if (undici && undici.Agent) {
|
|
388
|
+
sharedInsecureAgent = new undici.Agent({
|
|
389
|
+
connect: { rejectUnauthorized: false }
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
if (sharedInsecureAgent) {
|
|
394
|
+
fetchOptions.dispatcher = sharedInsecureAgent;
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
// Fallback to global setting (less secure, but only way without undici)
|
|
398
|
+
if (process.env.NODE_TLS_REJECT_UNAUTHORIZED !== '0') {
|
|
399
|
+
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
|
400
|
+
}
|
|
401
|
+
}
|
|
391
402
|
}
|
|
392
403
|
catch (e) {
|
|
393
404
|
// Ignore
|
|
@@ -432,21 +443,18 @@ class SingleFlight {
|
|
|
432
443
|
const existing = this.inFlight.get(key);
|
|
433
444
|
if (existing)
|
|
434
445
|
return existing;
|
|
435
|
-
const promise = this
|
|
446
|
+
const promise = (() => __awaiter(this, void 0, void 0, function* () {
|
|
447
|
+
try {
|
|
448
|
+
return yield fn();
|
|
449
|
+
}
|
|
450
|
+
finally {
|
|
451
|
+
this.inFlight.delete(key);
|
|
452
|
+
}
|
|
453
|
+
}))();
|
|
436
454
|
this.inFlight.set(key, promise);
|
|
437
455
|
return promise;
|
|
438
456
|
});
|
|
439
457
|
}
|
|
440
|
-
doExecute(key, fn) {
|
|
441
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
442
|
-
try {
|
|
443
|
-
return yield fn();
|
|
444
|
-
}
|
|
445
|
-
finally {
|
|
446
|
-
this.inFlight.delete(key);
|
|
447
|
-
}
|
|
448
|
-
});
|
|
449
|
-
}
|
|
450
458
|
}
|
|
451
459
|
/**
|
|
452
460
|
* Token Manager handles all token operations
|
|
@@ -462,6 +470,7 @@ class TokenManager {
|
|
|
462
470
|
*/
|
|
463
471
|
login(ctx, credentials, options) {
|
|
464
472
|
return __awaiter(this, void 0, void 0, function* () {
|
|
473
|
+
var _a, _b;
|
|
465
474
|
const url = this.joinURL(this.baseURL, this.config.login);
|
|
466
475
|
const contentType = this.config.contentType || 'application/json';
|
|
467
476
|
const headers = Object.assign(Object.assign({ 'Content-Type': contentType }, this.config.headers), options === null || options === void 0 ? void 0 : options.headers);
|
|
@@ -473,12 +482,16 @@ class TokenManager {
|
|
|
473
482
|
else {
|
|
474
483
|
requestBody = JSON.stringify(data);
|
|
475
484
|
}
|
|
485
|
+
const timeout = (_b = (_a = options === null || options === void 0 ? void 0 : options.timeout) !== null && _a !== void 0 ? _a : this.config.timeout) !== null && _b !== void 0 ? _b : 30000;
|
|
486
|
+
const controller = new AbortController();
|
|
487
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
476
488
|
let response;
|
|
477
489
|
try {
|
|
478
490
|
response = yield safeFetch(url, {
|
|
479
491
|
method: 'POST',
|
|
480
492
|
headers,
|
|
481
493
|
body: requestBody,
|
|
494
|
+
signal: controller.signal,
|
|
482
495
|
}, this.config);
|
|
483
496
|
}
|
|
484
497
|
catch (error) {
|
|
@@ -487,6 +500,9 @@ class TokenManager {
|
|
|
487
500
|
yield options.onError(authError, ctx);
|
|
488
501
|
throw authError;
|
|
489
502
|
}
|
|
503
|
+
finally {
|
|
504
|
+
clearTimeout(timeoutId);
|
|
505
|
+
}
|
|
490
506
|
if (!response.ok) {
|
|
491
507
|
const authError = new AuthError(`Login failed: ${response.status} ${response.statusText}`, response.status, response);
|
|
492
508
|
if (options === null || options === void 0 ? void 0 : options.onError)
|
|
@@ -542,6 +558,7 @@ class TokenManager {
|
|
|
542
558
|
*/
|
|
543
559
|
performRefresh(ctx, refreshToken, options, extraHeaders) {
|
|
544
560
|
return __awaiter(this, void 0, void 0, function* () {
|
|
561
|
+
var _a, _b;
|
|
545
562
|
const url = this.joinURL(this.baseURL, this.config.refresh);
|
|
546
563
|
const contentType = this.config.contentType || 'application/json';
|
|
547
564
|
const headers = Object.assign(Object.assign({ 'Content-Type': contentType }, this.config.headers), extraHeaders);
|
|
@@ -554,17 +571,24 @@ class TokenManager {
|
|
|
554
571
|
else {
|
|
555
572
|
requestBody = JSON.stringify(data);
|
|
556
573
|
}
|
|
574
|
+
const timeout = (_b = (_a = options === null || options === void 0 ? void 0 : options.timeout) !== null && _a !== void 0 ? _a : this.config.timeout) !== null && _b !== void 0 ? _b : 30000;
|
|
575
|
+
const controller = new AbortController();
|
|
576
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
557
577
|
let response;
|
|
558
578
|
try {
|
|
559
579
|
response = yield safeFetch(url, {
|
|
560
580
|
method: 'POST',
|
|
561
581
|
headers,
|
|
562
582
|
body: requestBody,
|
|
583
|
+
signal: controller.signal,
|
|
563
584
|
}, this.config);
|
|
564
585
|
}
|
|
565
586
|
catch (error) {
|
|
566
587
|
throw new AuthError(`Refresh request failed: ${error.message}`, undefined, undefined, undefined, error);
|
|
567
588
|
}
|
|
589
|
+
finally {
|
|
590
|
+
clearTimeout(timeoutId);
|
|
591
|
+
}
|
|
568
592
|
if (!response.ok) {
|
|
569
593
|
// 401/403 = invalid refresh token
|
|
570
594
|
if (response.status === 401 || response.status === 403) {
|
|
@@ -596,8 +620,8 @@ class TokenManager {
|
|
|
596
620
|
/**
|
|
597
621
|
* Ensure valid tokens (with automatic refresh)
|
|
598
622
|
*/
|
|
599
|
-
ensure(
|
|
600
|
-
return __awaiter(this,
|
|
623
|
+
ensure(ctx_1, options_1, headers_1) {
|
|
624
|
+
return __awaiter(this, arguments, void 0, function* (ctx, options, headers, force = false) {
|
|
601
625
|
var _a, _b, _c, _d, _e, _f;
|
|
602
626
|
const now = Math.floor(Date.now() / 1000);
|
|
603
627
|
const tokens = retrieveTokens(ctx, this.config.cookies);
|
|
@@ -605,12 +629,14 @@ class TokenManager {
|
|
|
605
629
|
if (!tokens.accessToken || !tokens.refreshToken || !tokens.expiresAt) {
|
|
606
630
|
return null;
|
|
607
631
|
}
|
|
608
|
-
// Token expired
|
|
609
|
-
if (isExpired(tokens.expiresAt, now, this.config.policy)) {
|
|
632
|
+
// Token expired or force refresh
|
|
633
|
+
if (force || isExpired(tokens.expiresAt, now, this.config.policy)) {
|
|
610
634
|
const flightKey = this.createFlightKey(tokens.refreshToken);
|
|
611
635
|
const bundle = yield this.singleFlight.execute(flightKey, () => this.refresh(ctx, tokens.refreshToken, options, headers));
|
|
612
636
|
if (!bundle)
|
|
613
637
|
return null;
|
|
638
|
+
// Ensure tokens are stored in the current context (in case of shared flight)
|
|
639
|
+
storeTokens(ctx, bundle, this.config.cookies);
|
|
614
640
|
return {
|
|
615
641
|
accessToken: bundle.accessToken,
|
|
616
642
|
expiresAt: bundle.accessExpiresAt,
|
|
@@ -623,6 +649,8 @@ class TokenManager {
|
|
|
623
649
|
const flightKey = this.createFlightKey(tokens.refreshToken);
|
|
624
650
|
const bundle = yield this.singleFlight.execute(flightKey, () => this.refresh(ctx, tokens.refreshToken, options, headers));
|
|
625
651
|
if (bundle) {
|
|
652
|
+
// Ensure tokens are stored in the current context (in case of shared flight)
|
|
653
|
+
storeTokens(ctx, bundle, this.config.cookies);
|
|
626
654
|
return {
|
|
627
655
|
accessToken: bundle.accessToken,
|
|
628
656
|
expiresAt: bundle.accessExpiresAt,
|
|
@@ -650,23 +678,33 @@ class TokenManager {
|
|
|
650
678
|
*/
|
|
651
679
|
logout(ctx) {
|
|
652
680
|
return __awaiter(this, void 0, void 0, function* () {
|
|
653
|
-
var _a;
|
|
681
|
+
var _a, _b;
|
|
654
682
|
// Optionally call logout endpoint
|
|
655
683
|
if (this.config.logout) {
|
|
684
|
+
const timeout = (_a = this.config.timeout) !== null && _a !== void 0 ? _a : 10000;
|
|
685
|
+
const controller = new AbortController();
|
|
686
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
656
687
|
try {
|
|
657
688
|
const url = this.joinURL(this.baseURL, this.config.logout);
|
|
658
689
|
const session = this.getSession(ctx);
|
|
659
690
|
const headers = {};
|
|
660
691
|
if (session === null || session === void 0 ? void 0 : session.accessToken) {
|
|
661
|
-
const injectFn = (
|
|
692
|
+
const injectFn = (_b = this.config.injectToken) !== null && _b !== void 0 ? _b : ((token, type) => `${type !== null && type !== void 0 ? type : 'Bearer'} ${token}`);
|
|
662
693
|
headers['Authorization'] = injectFn(session.accessToken, session.tokenType);
|
|
663
694
|
}
|
|
664
|
-
yield safeFetch(url, {
|
|
695
|
+
yield safeFetch(url, {
|
|
696
|
+
method: 'POST',
|
|
697
|
+
headers,
|
|
698
|
+
signal: controller.signal,
|
|
699
|
+
}, this.config);
|
|
665
700
|
}
|
|
666
701
|
catch (error) {
|
|
667
702
|
// Ignore logout endpoint errors
|
|
668
703
|
logger.debug('[TokenKit] Logout endpoint failed:', error);
|
|
669
704
|
}
|
|
705
|
+
finally {
|
|
706
|
+
clearTimeout(timeoutId);
|
|
707
|
+
}
|
|
670
708
|
}
|
|
671
709
|
clearTokens(ctx, this.config.cookies);
|
|
672
710
|
});
|