@mcp-z/oauth-microsoft 1.0.0 → 1.0.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/README.md +8 -0
- package/dist/cjs/index.d.cts +2 -1
- package/dist/cjs/index.d.ts +2 -1
- package/dist/cjs/index.js +4 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/lib/dcr-router.js.map +1 -1
- package/dist/cjs/lib/dcr-utils.js.map +1 -1
- package/dist/cjs/lib/dcr-verify.js.map +1 -1
- package/dist/cjs/lib/fetch-with-timeout.js.map +1 -1
- package/dist/cjs/lib/loopback-router.d.cts +8 -0
- package/dist/cjs/lib/loopback-router.d.ts +8 -0
- package/dist/cjs/lib/loopback-router.js +219 -0
- package/dist/cjs/lib/loopback-router.js.map +1 -0
- package/dist/cjs/lib/token-verifier.js.map +1 -1
- package/dist/cjs/providers/dcr.js.map +1 -1
- package/dist/cjs/providers/device-code.js.map +1 -1
- package/dist/cjs/providers/loopback-oauth.d.cts +15 -17
- package/dist/cjs/providers/loopback-oauth.d.ts +15 -17
- package/dist/cjs/providers/loopback-oauth.js +190 -156
- package/dist/cjs/providers/loopback-oauth.js.map +1 -1
- package/dist/cjs/schemas/index.js.map +1 -1
- package/dist/cjs/setup/config.d.cts +4 -1
- package/dist/cjs/setup/config.d.ts +4 -1
- package/dist/cjs/setup/config.js +3 -0
- package/dist/cjs/setup/config.js.map +1 -1
- package/dist/cjs/types.js.map +1 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/dcr-router.js.map +1 -1
- package/dist/esm/lib/dcr-utils.js.map +1 -1
- package/dist/esm/lib/dcr-verify.js.map +1 -1
- package/dist/esm/lib/fetch-with-timeout.js.map +1 -1
- package/dist/esm/lib/loopback-router.d.ts +8 -0
- package/dist/esm/lib/loopback-router.js +32 -0
- package/dist/esm/lib/loopback-router.js.map +1 -0
- package/dist/esm/lib/token-verifier.js.map +1 -1
- package/dist/esm/providers/dcr.js.map +1 -1
- package/dist/esm/providers/device-code.js +2 -2
- package/dist/esm/providers/device-code.js.map +1 -1
- package/dist/esm/providers/loopback-oauth.d.ts +15 -17
- package/dist/esm/providers/loopback-oauth.js +133 -115
- package/dist/esm/providers/loopback-oauth.js.map +1 -1
- package/dist/esm/schemas/index.js.map +1 -1
- package/dist/esm/setup/config.d.ts +4 -1
- package/dist/esm/setup/config.js +3 -0
- package/dist/esm/setup/config.js.map +1 -1
- package/dist/esm/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -32,6 +32,7 @@ _export(exports, {
|
|
|
32
32
|
}
|
|
33
33
|
});
|
|
34
34
|
var _oauth = require("@mcp-z/oauth");
|
|
35
|
+
var _crypto = require("crypto");
|
|
35
36
|
var _http = /*#__PURE__*/ _interop_require_wildcard(require("http"));
|
|
36
37
|
var _open = /*#__PURE__*/ _interop_require_default(require("open"));
|
|
37
38
|
var _fetchwithtimeoutts = require("../lib/fetch-with-timeout.js");
|
|
@@ -317,7 +318,7 @@ var LoopbackOAuthProvider = /*#__PURE__*/ function() {
|
|
|
317
318
|
* @returns Access token for API requests
|
|
318
319
|
*/ _proto.getAccessToken = function getAccessToken(accountId) {
|
|
319
320
|
return _async_to_generator(function() {
|
|
320
|
-
var _this_config, logger, service, tokenStore, effectiveAccountId, _tmp, storedToken, refreshedToken, error,
|
|
321
|
+
var _this_config, logger, service, tokenStore, effectiveAccountId, _tmp, storedToken, refreshedToken, error, _this_config1, clientId, tenantId, scope, redirectUri, _generatePKCE, codeVerifier, codeChallenge, stateId, authUrl, _ref, token, email;
|
|
321
322
|
return _ts_generator(this, function(_state) {
|
|
322
323
|
switch(_state.label){
|
|
323
324
|
case 0:
|
|
@@ -414,52 +415,49 @@ var LoopbackOAuthProvider = /*#__PURE__*/ function() {
|
|
|
414
415
|
9
|
|
415
416
|
];
|
|
416
417
|
case 9:
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
if (!headless) return [
|
|
418
|
+
_this_config1 = this.config, clientId = _this_config1.clientId, tenantId = _this_config1.tenantId, scope = _this_config1.scope, redirectUri = _this_config1.redirectUri;
|
|
419
|
+
if (!redirectUri) return [
|
|
420
420
|
3,
|
|
421
421
|
11
|
|
422
422
|
];
|
|
423
|
-
//
|
|
424
|
-
|
|
425
|
-
|
|
423
|
+
// Persistent callback mode (cloud deployment with configured redirect_uri)
|
|
424
|
+
_generatePKCE = (0, _oauth.generatePKCE)(), codeVerifier = _generatePKCE.verifier, codeChallenge = _generatePKCE.challenge;
|
|
425
|
+
stateId = (0, _crypto.randomUUID)();
|
|
426
|
+
// Store PKCE verifier for callback (5 minute TTL)
|
|
426
427
|
return [
|
|
427
428
|
4,
|
|
428
|
-
|
|
429
|
+
tokenStore.set("".concat(service, ":pending:").concat(stateId), {
|
|
430
|
+
codeVerifier: codeVerifier,
|
|
431
|
+
createdAt: Date.now()
|
|
432
|
+
}, 5 * 60 * 1000)
|
|
429
433
|
];
|
|
430
434
|
case 10:
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
// Build informational OAuth URL for headless mode
|
|
434
|
-
// Note: No redirect_uri included - user must use account-add tool which starts proper ephemeral server
|
|
435
|
+
_state.sent();
|
|
436
|
+
// Build auth URL with configured redirect_uri
|
|
435
437
|
authUrl = new URL("https://login.microsoftonline.com/".concat(tenantId, "/oauth2/v2.0/authorize"));
|
|
436
438
|
authUrl.searchParams.set('client_id', clientId);
|
|
439
|
+
authUrl.searchParams.set('redirect_uri', redirectUri);
|
|
437
440
|
authUrl.searchParams.set('response_type', 'code');
|
|
438
441
|
authUrl.searchParams.set('scope', scope);
|
|
439
442
|
authUrl.searchParams.set('response_mode', 'query');
|
|
443
|
+
authUrl.searchParams.set('code_challenge', codeChallenge);
|
|
444
|
+
authUrl.searchParams.set('code_challenge_method', 'S256');
|
|
445
|
+
authUrl.searchParams.set('state', stateId);
|
|
440
446
|
authUrl.searchParams.set('prompt', 'select_account');
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
hint = 'Use account-add to authenticate interactively';
|
|
447
|
-
}
|
|
448
|
-
baseDescriptor = {
|
|
447
|
+
logger.info('OAuth required - persistent callback mode', {
|
|
448
|
+
service: service,
|
|
449
|
+
redirectUri: redirectUri
|
|
450
|
+
});
|
|
451
|
+
throw new _typests.AuthRequiredError({
|
|
449
452
|
kind: 'auth_url',
|
|
450
|
-
provider:
|
|
451
|
-
url: authUrl.toString()
|
|
452
|
-
|
|
453
|
-
};
|
|
454
|
-
descriptor = effectiveAccountId ? _object_spread_props(_object_spread({}, baseDescriptor), {
|
|
455
|
-
accountId: effectiveAccountId
|
|
456
|
-
}) : baseDescriptor;
|
|
457
|
-
throw new _typests.AuthRequiredError(descriptor);
|
|
453
|
+
provider: service,
|
|
454
|
+
url: authUrl.toString()
|
|
455
|
+
});
|
|
458
456
|
case 11:
|
|
459
|
-
//
|
|
457
|
+
// Ephemeral callback mode (local development)
|
|
460
458
|
logger.info('Starting ephemeral OAuth flow', {
|
|
461
459
|
service: service,
|
|
462
|
-
headless: headless
|
|
460
|
+
headless: this.config.headless
|
|
463
461
|
});
|
|
464
462
|
return [
|
|
465
463
|
4,
|
|
@@ -467,7 +465,6 @@ var LoopbackOAuthProvider = /*#__PURE__*/ function() {
|
|
|
467
465
|
];
|
|
468
466
|
case 12:
|
|
469
467
|
_ref = _state.sent(), token = _ref.token, email = _ref.email;
|
|
470
|
-
// Store token with email as accountId
|
|
471
468
|
return [
|
|
472
469
|
4,
|
|
473
470
|
(0, _oauth.setToken)(tokenStore, {
|
|
@@ -477,7 +474,6 @@ var LoopbackOAuthProvider = /*#__PURE__*/ function() {
|
|
|
477
474
|
];
|
|
478
475
|
case 13:
|
|
479
476
|
_state.sent();
|
|
480
|
-
// Register account in account management system
|
|
481
477
|
return [
|
|
482
478
|
4,
|
|
483
479
|
(0, _oauth.addAccount)(tokenStore, {
|
|
@@ -487,7 +483,6 @@ var LoopbackOAuthProvider = /*#__PURE__*/ function() {
|
|
|
487
483
|
];
|
|
488
484
|
case 14:
|
|
489
485
|
_state.sent();
|
|
490
|
-
// Set as active account so subsequent getAccessToken() calls find it
|
|
491
486
|
return [
|
|
492
487
|
4,
|
|
493
488
|
(0, _oauth.setActiveAccount)(tokenStore, {
|
|
@@ -497,7 +492,6 @@ var LoopbackOAuthProvider = /*#__PURE__*/ function() {
|
|
|
497
492
|
];
|
|
498
493
|
case 15:
|
|
499
494
|
_state.sent();
|
|
500
|
-
// Store account metadata (email, added timestamp)
|
|
501
495
|
return [
|
|
502
496
|
4,
|
|
503
497
|
(0, _oauth.setAccountInfo)(tokenStore, {
|
|
@@ -538,86 +532,6 @@ var LoopbackOAuthProvider = /*#__PURE__*/ function() {
|
|
|
538
532
|
};
|
|
539
533
|
};
|
|
540
534
|
/**
|
|
541
|
-
* Authenticate new account with OAuth flow
|
|
542
|
-
* Triggers account selection, stores token, registers account
|
|
543
|
-
*
|
|
544
|
-
* @returns Email address of newly authenticated account
|
|
545
|
-
* @throws Error in headless mode (cannot open browser for OAuth)
|
|
546
|
-
*/ _proto.authenticateNewAccount = function authenticateNewAccount() {
|
|
547
|
-
return _async_to_generator(function() {
|
|
548
|
-
var _this_config, logger, headless, service, tokenStore, _ref, token, email;
|
|
549
|
-
return _ts_generator(this, function(_state) {
|
|
550
|
-
switch(_state.label){
|
|
551
|
-
case 0:
|
|
552
|
-
_this_config = this.config, logger = _this_config.logger, headless = _this_config.headless, service = _this_config.service, tokenStore = _this_config.tokenStore;
|
|
553
|
-
if (headless) {
|
|
554
|
-
throw new Error('Cannot authenticate new account in headless mode - interactive OAuth required');
|
|
555
|
-
}
|
|
556
|
-
logger.info('Starting new account authentication', {
|
|
557
|
-
service: service
|
|
558
|
-
});
|
|
559
|
-
return [
|
|
560
|
-
4,
|
|
561
|
-
this.performEphemeralOAuthFlow()
|
|
562
|
-
];
|
|
563
|
-
case 1:
|
|
564
|
-
_ref = _state.sent(), token = _ref.token, email = _ref.email;
|
|
565
|
-
// Store token
|
|
566
|
-
return [
|
|
567
|
-
4,
|
|
568
|
-
(0, _oauth.setToken)(tokenStore, {
|
|
569
|
-
accountId: email,
|
|
570
|
-
service: service
|
|
571
|
-
}, token)
|
|
572
|
-
];
|
|
573
|
-
case 2:
|
|
574
|
-
_state.sent();
|
|
575
|
-
// Register account
|
|
576
|
-
return [
|
|
577
|
-
4,
|
|
578
|
-
(0, _oauth.addAccount)(tokenStore, {
|
|
579
|
-
service: service,
|
|
580
|
-
accountId: email
|
|
581
|
-
})
|
|
582
|
-
];
|
|
583
|
-
case 3:
|
|
584
|
-
_state.sent();
|
|
585
|
-
// Set as active account
|
|
586
|
-
return [
|
|
587
|
-
4,
|
|
588
|
-
(0, _oauth.setActiveAccount)(tokenStore, {
|
|
589
|
-
service: service,
|
|
590
|
-
accountId: email
|
|
591
|
-
})
|
|
592
|
-
];
|
|
593
|
-
case 4:
|
|
594
|
-
_state.sent();
|
|
595
|
-
// Store account metadata
|
|
596
|
-
return [
|
|
597
|
-
4,
|
|
598
|
-
(0, _oauth.setAccountInfo)(tokenStore, {
|
|
599
|
-
service: service,
|
|
600
|
-
accountId: email
|
|
601
|
-
}, {
|
|
602
|
-
email: email,
|
|
603
|
-
addedAt: new Date().toISOString()
|
|
604
|
-
})
|
|
605
|
-
];
|
|
606
|
-
case 5:
|
|
607
|
-
_state.sent();
|
|
608
|
-
logger.info('New account authenticated', {
|
|
609
|
-
service: service,
|
|
610
|
-
email: email
|
|
611
|
-
});
|
|
612
|
-
return [
|
|
613
|
-
2,
|
|
614
|
-
email
|
|
615
|
-
];
|
|
616
|
-
}
|
|
617
|
-
});
|
|
618
|
-
}).call(this);
|
|
619
|
-
};
|
|
620
|
-
/**
|
|
621
535
|
* Get user email from Microsoft Graph API (pure query)
|
|
622
536
|
* Used to query email for existing authenticated account
|
|
623
537
|
*
|
|
@@ -677,24 +591,6 @@ var LoopbackOAuthProvider = /*#__PURE__*/ function() {
|
|
|
677
591
|
});
|
|
678
592
|
}).call(this);
|
|
679
593
|
};
|
|
680
|
-
/**
|
|
681
|
-
* Check for existing accounts in token storage (incremental OAuth detection)
|
|
682
|
-
*
|
|
683
|
-
* Uses key-utils helper for forward compatibility with key format changes.
|
|
684
|
-
*
|
|
685
|
-
* @returns Array of account IDs that have tokens for this service
|
|
686
|
-
*/ _proto.getExistingAccounts = function getExistingAccounts() {
|
|
687
|
-
return _async_to_generator(function() {
|
|
688
|
-
var _this_config, service, tokenStore;
|
|
689
|
-
return _ts_generator(this, function(_state) {
|
|
690
|
-
_this_config = this.config, service = _this_config.service, tokenStore = _this_config.tokenStore;
|
|
691
|
-
return [
|
|
692
|
-
2,
|
|
693
|
-
(0, _oauth.listAccountIds)(tokenStore, service)
|
|
694
|
-
];
|
|
695
|
-
});
|
|
696
|
-
}).call(this);
|
|
697
|
-
};
|
|
698
594
|
_proto.isTokenValid = function isTokenValid(token) {
|
|
699
595
|
if (!token.expiresAt) return true; // No expiry = assume valid
|
|
700
596
|
return Date.now() < token.expiresAt - 60000; // 1 minute buffer
|
|
@@ -754,46 +650,50 @@ var LoopbackOAuthProvider = /*#__PURE__*/ function() {
|
|
|
754
650
|
};
|
|
755
651
|
_proto.performEphemeralOAuthFlow = function performEphemeralOAuthFlow() {
|
|
756
652
|
return _async_to_generator(function() {
|
|
757
|
-
var _this, _this_config, clientId, tenantId, scope, headless, logger, configRedirectUri,
|
|
653
|
+
var _this, _this_config, clientId, tenantId, scope, headless, logger, configRedirectUri, listenHost, listenPort, callbackPath, useConfiguredUri, parsed, isLoopback, envPort;
|
|
758
654
|
return _ts_generator(this, function(_state) {
|
|
759
655
|
_this = this;
|
|
760
656
|
_this_config = this.config, clientId = _this_config.clientId, tenantId = _this_config.tenantId, scope = _this_config.scope, headless = _this_config.headless, logger = _this_config.logger, configRedirectUri = _this_config.redirectUri;
|
|
761
|
-
//
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
657
|
+
// Server listen configuration (where ephemeral server binds)
|
|
658
|
+
listenHost = 'localhost'; // Default: localhost for ephemeral loopback
|
|
659
|
+
listenPort = 0; // Default: OS-assigned ephemeral port
|
|
660
|
+
// Redirect URI configuration (what goes in auth URL and token exchange)
|
|
765
661
|
callbackPath = '/callback'; // Default callback path
|
|
766
662
|
useConfiguredUri = false;
|
|
767
663
|
if (configRedirectUri) {
|
|
768
664
|
try {
|
|
769
665
|
parsed = new URL(configRedirectUri);
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
targetPort = Number.parseInt(parsed.port, 10);
|
|
666
|
+
isLoopback = parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1';
|
|
667
|
+
if (isLoopback) {
|
|
668
|
+
// Local development: Listen on specific loopback address/port
|
|
669
|
+
listenHost = parsed.hostname;
|
|
670
|
+
listenPort = parsed.port ? Number.parseInt(parsed.port, 10) : 0;
|
|
776
671
|
} else {
|
|
777
|
-
|
|
672
|
+
// Cloud deployment: Listen on 0.0.0.0 with PORT from environment
|
|
673
|
+
// The redirectUri is the PUBLIC URL (e.g., https://example.com/oauth/callback)
|
|
674
|
+
// The server listens on 0.0.0.0:PORT and the load balancer routes to it
|
|
675
|
+
listenHost = '0.0.0.0';
|
|
676
|
+
envPort = process.env.PORT ? Number.parseInt(process.env.PORT, 10) : undefined;
|
|
677
|
+
listenPort = envPort && Number.isFinite(envPort) ? envPort : 8080;
|
|
778
678
|
}
|
|
779
|
-
// Extract
|
|
679
|
+
// Extract callback path from URL
|
|
780
680
|
if (parsed.pathname && parsed.pathname !== '/') {
|
|
781
681
|
callbackPath = parsed.pathname;
|
|
782
682
|
}
|
|
783
683
|
useConfiguredUri = true;
|
|
784
684
|
logger.debug('Using configured redirect URI', {
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
685
|
+
listenHost: listenHost,
|
|
686
|
+
listenPort: listenPort,
|
|
687
|
+
callbackPath: callbackPath,
|
|
688
|
+
redirectUri: configRedirectUri,
|
|
689
|
+
isLoopback: isLoopback
|
|
790
690
|
});
|
|
791
691
|
} catch (error) {
|
|
792
692
|
logger.warn('Failed to parse redirectUri, using ephemeral defaults', {
|
|
793
693
|
redirectUri: configRedirectUri,
|
|
794
694
|
error: _instanceof(error, Error) ? error.message : String(error)
|
|
795
695
|
});
|
|
796
|
-
// Continue with defaults (
|
|
696
|
+
// Continue with defaults (localhost, port 0, http, /callback)
|
|
797
697
|
}
|
|
798
698
|
}
|
|
799
699
|
return [
|
|
@@ -928,8 +828,11 @@ var LoopbackOAuthProvider = /*#__PURE__*/ function() {
|
|
|
928
828
|
});
|
|
929
829
|
}).call(_this);
|
|
930
830
|
});
|
|
931
|
-
// Listen on
|
|
932
|
-
|
|
831
|
+
// Listen on configured host/port
|
|
832
|
+
// - For loopback (default): localhost with OS-assigned port
|
|
833
|
+
// - For configured loopback: specific localhost port from redirectUri
|
|
834
|
+
// - For cloud deployment: 0.0.0.0:${PORT} from environment
|
|
835
|
+
server.listen(listenPort, listenHost, function() {
|
|
933
836
|
var address = server === null || server === void 0 ? void 0 : server.address();
|
|
934
837
|
if (!address || typeof address === 'string') {
|
|
935
838
|
server === null || server === void 0 ? void 0 : server.close();
|
|
@@ -939,11 +842,11 @@ var LoopbackOAuthProvider = /*#__PURE__*/ function() {
|
|
|
939
842
|
serverPort = address.port;
|
|
940
843
|
// Construct final redirect URI
|
|
941
844
|
if (useConfiguredUri && configRedirectUri) {
|
|
942
|
-
// Use configured redirect URI as-is for
|
|
845
|
+
// Use configured redirect URI as-is (public URL for cloud, or specific local URL)
|
|
943
846
|
finalRedirectUri = configRedirectUri;
|
|
944
847
|
} else {
|
|
945
|
-
// Construct ephemeral redirect URI with actual server port
|
|
946
|
-
finalRedirectUri = "
|
|
848
|
+
// Construct ephemeral redirect URI with actual server port (default local behavior)
|
|
849
|
+
finalRedirectUri = "http://localhost:".concat(serverPort).concat(callbackPath);
|
|
947
850
|
}
|
|
948
851
|
// Build Microsoft auth URL
|
|
949
852
|
var authUrl = new URL("https://login.microsoftonline.com/".concat(tenantId, "/oauth2/v2.0/authorize"));
|
|
@@ -1111,6 +1014,137 @@ var LoopbackOAuthProvider = /*#__PURE__*/ function() {
|
|
|
1111
1014
|
}).call(this);
|
|
1112
1015
|
};
|
|
1113
1016
|
/**
|
|
1017
|
+
* Handle OAuth callback from persistent endpoint.
|
|
1018
|
+
* Used by HTTP servers with configured redirectUri.
|
|
1019
|
+
*
|
|
1020
|
+
* @param params - OAuth callback parameters
|
|
1021
|
+
* @returns Email and cached token
|
|
1022
|
+
*/ _proto.handleOAuthCallback = function handleOAuthCallback(params) {
|
|
1023
|
+
return _async_to_generator(function() {
|
|
1024
|
+
var code, state, _this_config, logger, service, tokenStore, redirectUri, pendingKey, pendingAuth, tokenResponse, cachedToken, email;
|
|
1025
|
+
return _ts_generator(this, function(_state) {
|
|
1026
|
+
switch(_state.label){
|
|
1027
|
+
case 0:
|
|
1028
|
+
code = params.code, state = params.state;
|
|
1029
|
+
_this_config = this.config, logger = _this_config.logger, service = _this_config.service, tokenStore = _this_config.tokenStore, redirectUri = _this_config.redirectUri;
|
|
1030
|
+
if (!state) {
|
|
1031
|
+
throw new Error('Missing state parameter in OAuth callback');
|
|
1032
|
+
}
|
|
1033
|
+
if (!redirectUri) {
|
|
1034
|
+
throw new Error('handleOAuthCallback requires configured redirectUri');
|
|
1035
|
+
}
|
|
1036
|
+
// Load pending auth (includes PKCE verifier)
|
|
1037
|
+
pendingKey = "".concat(service, ":pending:").concat(state);
|
|
1038
|
+
return [
|
|
1039
|
+
4,
|
|
1040
|
+
tokenStore.get(pendingKey)
|
|
1041
|
+
];
|
|
1042
|
+
case 1:
|
|
1043
|
+
pendingAuth = _state.sent();
|
|
1044
|
+
if (!pendingAuth) {
|
|
1045
|
+
throw new Error('Invalid or expired OAuth state. Please try again.');
|
|
1046
|
+
}
|
|
1047
|
+
if (!(Date.now() - pendingAuth.createdAt > 5 * 60 * 1000)) return [
|
|
1048
|
+
3,
|
|
1049
|
+
3
|
|
1050
|
+
];
|
|
1051
|
+
return [
|
|
1052
|
+
4,
|
|
1053
|
+
tokenStore.delete(pendingKey)
|
|
1054
|
+
];
|
|
1055
|
+
case 2:
|
|
1056
|
+
_state.sent();
|
|
1057
|
+
throw new Error('OAuth state expired. Please try again.');
|
|
1058
|
+
case 3:
|
|
1059
|
+
logger.info('Processing OAuth callback', {
|
|
1060
|
+
service: service,
|
|
1061
|
+
state: state
|
|
1062
|
+
});
|
|
1063
|
+
return [
|
|
1064
|
+
4,
|
|
1065
|
+
this.exchangeCodeForToken(code, pendingAuth.codeVerifier, redirectUri)
|
|
1066
|
+
];
|
|
1067
|
+
case 4:
|
|
1068
|
+
tokenResponse = _state.sent();
|
|
1069
|
+
// Create cached token
|
|
1070
|
+
cachedToken = _object_spread({
|
|
1071
|
+
accessToken: tokenResponse.access_token,
|
|
1072
|
+
refreshToken: tokenResponse.refresh_token,
|
|
1073
|
+
expiresAt: tokenResponse.expires_in ? Date.now() + tokenResponse.expires_in * 1000 : undefined
|
|
1074
|
+
}, tokenResponse.scope !== undefined && {
|
|
1075
|
+
scope: tokenResponse.scope
|
|
1076
|
+
});
|
|
1077
|
+
return [
|
|
1078
|
+
4,
|
|
1079
|
+
this.fetchUserEmailFromToken(tokenResponse.access_token)
|
|
1080
|
+
];
|
|
1081
|
+
case 5:
|
|
1082
|
+
email = _state.sent();
|
|
1083
|
+
// Store token
|
|
1084
|
+
return [
|
|
1085
|
+
4,
|
|
1086
|
+
(0, _oauth.setToken)(tokenStore, {
|
|
1087
|
+
accountId: email,
|
|
1088
|
+
service: service
|
|
1089
|
+
}, cachedToken)
|
|
1090
|
+
];
|
|
1091
|
+
case 6:
|
|
1092
|
+
_state.sent();
|
|
1093
|
+
// Add account and set as active
|
|
1094
|
+
return [
|
|
1095
|
+
4,
|
|
1096
|
+
(0, _oauth.addAccount)(tokenStore, {
|
|
1097
|
+
service: service,
|
|
1098
|
+
accountId: email
|
|
1099
|
+
})
|
|
1100
|
+
];
|
|
1101
|
+
case 7:
|
|
1102
|
+
_state.sent();
|
|
1103
|
+
return [
|
|
1104
|
+
4,
|
|
1105
|
+
(0, _oauth.setActiveAccount)(tokenStore, {
|
|
1106
|
+
service: service,
|
|
1107
|
+
accountId: email
|
|
1108
|
+
})
|
|
1109
|
+
];
|
|
1110
|
+
case 8:
|
|
1111
|
+
_state.sent();
|
|
1112
|
+
// Store account metadata
|
|
1113
|
+
return [
|
|
1114
|
+
4,
|
|
1115
|
+
(0, _oauth.setAccountInfo)(tokenStore, {
|
|
1116
|
+
service: service,
|
|
1117
|
+
accountId: email
|
|
1118
|
+
}, {
|
|
1119
|
+
email: email,
|
|
1120
|
+
addedAt: new Date().toISOString()
|
|
1121
|
+
})
|
|
1122
|
+
];
|
|
1123
|
+
case 9:
|
|
1124
|
+
_state.sent();
|
|
1125
|
+
// Clean up pending auth
|
|
1126
|
+
return [
|
|
1127
|
+
4,
|
|
1128
|
+
tokenStore.delete(pendingKey)
|
|
1129
|
+
];
|
|
1130
|
+
case 10:
|
|
1131
|
+
_state.sent();
|
|
1132
|
+
logger.info('OAuth callback completed', {
|
|
1133
|
+
service: service,
|
|
1134
|
+
email: email
|
|
1135
|
+
});
|
|
1136
|
+
return [
|
|
1137
|
+
2,
|
|
1138
|
+
{
|
|
1139
|
+
email: email,
|
|
1140
|
+
token: cachedToken
|
|
1141
|
+
}
|
|
1142
|
+
];
|
|
1143
|
+
}
|
|
1144
|
+
});
|
|
1145
|
+
}).call(this);
|
|
1146
|
+
};
|
|
1147
|
+
/**
|
|
1114
1148
|
* Create auth middleware for single-user context (single active account per service)
|
|
1115
1149
|
*
|
|
1116
1150
|
* Single-user mode:
|