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