integrate-sdk 0.8.26 → 0.8.28-dev.0
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/dist/adapters/auto-routes.js +517 -128
- package/dist/adapters/base-handler.d.ts +19 -11
- package/dist/adapters/base-handler.d.ts.map +1 -1
- package/dist/adapters/index.js +517 -128
- package/dist/adapters/nextjs.js +517 -128
- package/dist/adapters/node.js +517 -128
- package/dist/adapters/svelte-kit.js +517 -128
- package/dist/adapters/tanstack-start.js +517 -128
- package/dist/index.js +517 -128
- package/dist/oauth.js +517 -128
- package/dist/server.js +517 -128
- package/dist/src/adapters/base-handler.d.ts +19 -11
- package/dist/src/adapters/base-handler.d.ts.map +1 -1
- package/dist/src/client.d.ts +68 -12
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/config/types.d.ts +39 -23
- package/dist/src/config/types.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/oauth/email-fetcher.d.ts +14 -0
- package/dist/src/oauth/email-fetcher.d.ts.map +1 -0
- package/dist/src/oauth/indexeddb-storage.d.ts +68 -0
- package/dist/src/oauth/indexeddb-storage.d.ts.map +1 -0
- package/dist/src/oauth/manager.d.ts +67 -45
- package/dist/src/oauth/manager.d.ts.map +1 -1
- package/dist/src/oauth/types.d.ts +19 -0
- package/dist/src/oauth/types.d.ts.map +1 -1
- package/dist/src/server.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -627,6 +627,277 @@ class OAuthWindowManager {
|
|
|
627
627
|
}
|
|
628
628
|
}
|
|
629
629
|
|
|
630
|
+
// ../oauth/indexeddb-storage.ts
|
|
631
|
+
class IndexedDBStorage {
|
|
632
|
+
db = null;
|
|
633
|
+
initPromise = null;
|
|
634
|
+
async init() {
|
|
635
|
+
if (this.db) {
|
|
636
|
+
return this.db;
|
|
637
|
+
}
|
|
638
|
+
if (this.initPromise) {
|
|
639
|
+
return this.initPromise;
|
|
640
|
+
}
|
|
641
|
+
this.initPromise = new Promise((resolve, reject) => {
|
|
642
|
+
if (typeof window === "undefined" || !window.indexedDB) {
|
|
643
|
+
reject(new Error("IndexedDB is not available in this environment"));
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
const request = window.indexedDB.open(DB_NAME, DB_VERSION);
|
|
647
|
+
request.onerror = () => {
|
|
648
|
+
this.initPromise = null;
|
|
649
|
+
reject(new Error(`Failed to open IndexedDB: ${request.error?.message}`));
|
|
650
|
+
};
|
|
651
|
+
request.onsuccess = () => {
|
|
652
|
+
this.db = request.result;
|
|
653
|
+
this.initPromise = null;
|
|
654
|
+
resolve(this.db);
|
|
655
|
+
};
|
|
656
|
+
request.onupgradeneeded = (event) => {
|
|
657
|
+
const db = event.target.result;
|
|
658
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
659
|
+
const store = db.createObjectStore(STORE_NAME, { keyPath: "accountId" });
|
|
660
|
+
store.createIndex("provider", "provider", { unique: false });
|
|
661
|
+
store.createIndex("email", "email", { unique: false });
|
|
662
|
+
store.createIndex("provider_email", ["provider", "email"], { unique: true });
|
|
663
|
+
}
|
|
664
|
+
};
|
|
665
|
+
});
|
|
666
|
+
return this.initPromise;
|
|
667
|
+
}
|
|
668
|
+
generateAccountId(provider, email) {
|
|
669
|
+
const str = `${provider}:${email}`;
|
|
670
|
+
let hash = 0;
|
|
671
|
+
for (let i = 0;i < str.length; i++) {
|
|
672
|
+
const char = str.charCodeAt(i);
|
|
673
|
+
hash = (hash << 5) - hash + char;
|
|
674
|
+
hash = hash & hash;
|
|
675
|
+
}
|
|
676
|
+
return `${provider}_${Math.abs(hash).toString(36)}`;
|
|
677
|
+
}
|
|
678
|
+
async saveToken(provider, email, tokenData) {
|
|
679
|
+
const db = await this.init();
|
|
680
|
+
const accountId = this.generateAccountId(provider, email);
|
|
681
|
+
const now = Date.now();
|
|
682
|
+
const entry = {
|
|
683
|
+
provider,
|
|
684
|
+
email,
|
|
685
|
+
accountId,
|
|
686
|
+
tokenData,
|
|
687
|
+
createdAt: now,
|
|
688
|
+
updatedAt: now
|
|
689
|
+
};
|
|
690
|
+
return new Promise((resolve, reject) => {
|
|
691
|
+
const transaction = db.transaction([STORE_NAME], "readwrite");
|
|
692
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
693
|
+
const getRequest = store.get(accountId);
|
|
694
|
+
getRequest.onsuccess = () => {
|
|
695
|
+
const existing = getRequest.result;
|
|
696
|
+
if (existing) {
|
|
697
|
+
entry.createdAt = existing.createdAt;
|
|
698
|
+
}
|
|
699
|
+
const putRequest = store.put(entry);
|
|
700
|
+
putRequest.onsuccess = () => resolve();
|
|
701
|
+
putRequest.onerror = () => reject(new Error(`Failed to save token: ${putRequest.error?.message}`));
|
|
702
|
+
};
|
|
703
|
+
getRequest.onerror = () => reject(new Error(`Failed to check existing token: ${getRequest.error?.message}`));
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
async getToken(provider, email) {
|
|
707
|
+
const db = await this.init();
|
|
708
|
+
const accountId = this.generateAccountId(provider, email);
|
|
709
|
+
return new Promise((resolve, reject) => {
|
|
710
|
+
const transaction = db.transaction([STORE_NAME], "readonly");
|
|
711
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
712
|
+
const request = store.get(accountId);
|
|
713
|
+
request.onsuccess = () => {
|
|
714
|
+
const entry = request.result;
|
|
715
|
+
resolve(entry?.tokenData);
|
|
716
|
+
};
|
|
717
|
+
request.onerror = () => reject(new Error(`Failed to get token: ${request.error?.message}`));
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
async getTokensByProvider(provider) {
|
|
721
|
+
const db = await this.init();
|
|
722
|
+
const tokens = new Map;
|
|
723
|
+
return new Promise((resolve, reject) => {
|
|
724
|
+
const transaction = db.transaction([STORE_NAME], "readonly");
|
|
725
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
726
|
+
const index = store.index("provider");
|
|
727
|
+
const request = index.getAll(provider);
|
|
728
|
+
request.onsuccess = () => {
|
|
729
|
+
const entries = request.result;
|
|
730
|
+
for (const entry of entries) {
|
|
731
|
+
tokens.set(entry.email, entry.tokenData);
|
|
732
|
+
}
|
|
733
|
+
resolve(tokens);
|
|
734
|
+
};
|
|
735
|
+
request.onerror = () => reject(new Error(`Failed to get tokens: ${request.error?.message}`));
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
async listAccounts(provider) {
|
|
739
|
+
const db = await this.init();
|
|
740
|
+
return new Promise((resolve, reject) => {
|
|
741
|
+
const transaction = db.transaction([STORE_NAME], "readonly");
|
|
742
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
743
|
+
const index = store.index("provider");
|
|
744
|
+
const request = index.getAll(provider);
|
|
745
|
+
request.onsuccess = () => {
|
|
746
|
+
const entries = request.result;
|
|
747
|
+
const accounts = entries.map((entry) => ({
|
|
748
|
+
email: entry.email,
|
|
749
|
+
accountId: entry.accountId,
|
|
750
|
+
expiresAt: entry.tokenData.expiresAt,
|
|
751
|
+
scopes: entry.tokenData.scopes,
|
|
752
|
+
createdAt: entry.createdAt
|
|
753
|
+
}));
|
|
754
|
+
resolve(accounts);
|
|
755
|
+
};
|
|
756
|
+
request.onerror = () => reject(new Error(`Failed to list accounts: ${request.error?.message}`));
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
async deleteToken(provider, email) {
|
|
760
|
+
const db = await this.init();
|
|
761
|
+
const accountId = this.generateAccountId(provider, email);
|
|
762
|
+
return new Promise((resolve, reject) => {
|
|
763
|
+
const transaction = db.transaction([STORE_NAME], "readwrite");
|
|
764
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
765
|
+
const request = store.delete(accountId);
|
|
766
|
+
request.onsuccess = () => resolve();
|
|
767
|
+
request.onerror = () => reject(new Error(`Failed to delete token: ${request.error?.message}`));
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
async deleteTokensByProvider(provider) {
|
|
771
|
+
const db = await this.init();
|
|
772
|
+
return new Promise((resolve, reject) => {
|
|
773
|
+
const transaction = db.transaction([STORE_NAME], "readwrite");
|
|
774
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
775
|
+
const index = store.index("provider");
|
|
776
|
+
const request = index.getAll(provider);
|
|
777
|
+
request.onsuccess = () => {
|
|
778
|
+
const entries = request.result;
|
|
779
|
+
const deletePromises = entries.map((entry) => {
|
|
780
|
+
return new Promise((resolveDelete, rejectDelete) => {
|
|
781
|
+
const deleteRequest = store.delete(entry.accountId);
|
|
782
|
+
deleteRequest.onsuccess = () => resolveDelete();
|
|
783
|
+
deleteRequest.onerror = () => rejectDelete(deleteRequest.error);
|
|
784
|
+
});
|
|
785
|
+
});
|
|
786
|
+
Promise.all(deletePromises).then(() => resolve()).catch((error) => reject(error));
|
|
787
|
+
};
|
|
788
|
+
request.onerror = () => reject(new Error(`Failed to delete tokens: ${request.error?.message}`));
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
async clearAll() {
|
|
792
|
+
const db = await this.init();
|
|
793
|
+
return new Promise((resolve, reject) => {
|
|
794
|
+
const transaction = db.transaction([STORE_NAME], "readwrite");
|
|
795
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
796
|
+
const request = store.clear();
|
|
797
|
+
request.onsuccess = () => resolve();
|
|
798
|
+
request.onerror = () => reject(new Error(`Failed to clear tokens: ${request.error?.message}`));
|
|
799
|
+
});
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
var DB_NAME = "integrate_oauth_tokens", DB_VERSION = 1, STORE_NAME = "tokens";
|
|
803
|
+
|
|
804
|
+
// ../oauth/email-fetcher.ts
|
|
805
|
+
async function fetchUserEmail(provider, tokenData) {
|
|
806
|
+
try {
|
|
807
|
+
switch (provider.toLowerCase()) {
|
|
808
|
+
case "github":
|
|
809
|
+
return await fetchGitHubEmail(tokenData.accessToken);
|
|
810
|
+
case "gmail":
|
|
811
|
+
case "google":
|
|
812
|
+
return await fetchGoogleEmail(tokenData.accessToken);
|
|
813
|
+
case "notion":
|
|
814
|
+
return await fetchNotionEmail(tokenData.accessToken);
|
|
815
|
+
default:
|
|
816
|
+
return tokenData.email;
|
|
817
|
+
}
|
|
818
|
+
} catch (error) {
|
|
819
|
+
console.error(`Failed to fetch email for ${provider}:`, error);
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
async function fetchGitHubEmail(accessToken) {
|
|
824
|
+
try {
|
|
825
|
+
const userResponse = await fetch("https://api.github.com/user", {
|
|
826
|
+
headers: {
|
|
827
|
+
Authorization: `Bearer ${accessToken}`,
|
|
828
|
+
Accept: "application/vnd.github.v3+json"
|
|
829
|
+
}
|
|
830
|
+
});
|
|
831
|
+
if (!userResponse.ok) {
|
|
832
|
+
return;
|
|
833
|
+
}
|
|
834
|
+
const user = await userResponse.json();
|
|
835
|
+
if (user.email) {
|
|
836
|
+
return user.email;
|
|
837
|
+
}
|
|
838
|
+
const emailsResponse = await fetch("https://api.github.com/user/emails", {
|
|
839
|
+
headers: {
|
|
840
|
+
Authorization: `Bearer ${accessToken}`,
|
|
841
|
+
Accept: "application/vnd.github.v3+json"
|
|
842
|
+
}
|
|
843
|
+
});
|
|
844
|
+
if (!emailsResponse.ok) {
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
const emails = await emailsResponse.json();
|
|
848
|
+
const primaryEmail = emails.find((e) => e.primary && e.verified);
|
|
849
|
+
if (primaryEmail) {
|
|
850
|
+
return primaryEmail.email;
|
|
851
|
+
}
|
|
852
|
+
const verifiedEmail = emails.find((e) => e.verified);
|
|
853
|
+
if (verifiedEmail) {
|
|
854
|
+
return verifiedEmail.email;
|
|
855
|
+
}
|
|
856
|
+
if (emails.length > 0 && emails[0]?.email) {
|
|
857
|
+
return emails[0].email;
|
|
858
|
+
}
|
|
859
|
+
return;
|
|
860
|
+
} catch (error) {
|
|
861
|
+
console.error("Failed to fetch GitHub email:", error);
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
async function fetchGoogleEmail(accessToken) {
|
|
866
|
+
try {
|
|
867
|
+
const response = await fetch("https://www.googleapis.com/oauth2/v2/userinfo", {
|
|
868
|
+
headers: {
|
|
869
|
+
Authorization: `Bearer ${accessToken}`
|
|
870
|
+
}
|
|
871
|
+
});
|
|
872
|
+
if (!response.ok) {
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
const user = await response.json();
|
|
876
|
+
return user.email;
|
|
877
|
+
} catch (error) {
|
|
878
|
+
console.error("Failed to fetch Google email:", error);
|
|
879
|
+
return;
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
async function fetchNotionEmail(accessToken) {
|
|
883
|
+
try {
|
|
884
|
+
const response = await fetch("https://api.notion.com/v1/users/me", {
|
|
885
|
+
headers: {
|
|
886
|
+
Authorization: `Bearer ${accessToken}`,
|
|
887
|
+
"Notion-Version": "2022-06-28"
|
|
888
|
+
}
|
|
889
|
+
});
|
|
890
|
+
if (!response.ok) {
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
const user = await response.json();
|
|
894
|
+
return user.person?.email;
|
|
895
|
+
} catch (error) {
|
|
896
|
+
console.error("Failed to fetch Notion email:", error);
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
|
|
630
901
|
// ../oauth/manager.ts
|
|
631
902
|
class OAuthManager {
|
|
632
903
|
pendingAuths = new Map;
|
|
@@ -638,7 +909,8 @@ class OAuthManager {
|
|
|
638
909
|
getTokenCallback;
|
|
639
910
|
setTokenCallback;
|
|
640
911
|
removeTokenCallback;
|
|
641
|
-
|
|
912
|
+
indexedDBStorage;
|
|
913
|
+
skipLocalStorage = false;
|
|
642
914
|
constructor(oauthApiBase, flowConfig, apiBaseUrl, tokenCallbacks) {
|
|
643
915
|
this.oauthApiBase = oauthApiBase;
|
|
644
916
|
this.apiBaseUrl = apiBaseUrl;
|
|
@@ -651,7 +923,7 @@ class OAuthManager {
|
|
|
651
923
|
this.getTokenCallback = tokenCallbacks?.getProviderToken;
|
|
652
924
|
this.setTokenCallback = tokenCallbacks?.setProviderToken;
|
|
653
925
|
this.removeTokenCallback = tokenCallbacks?.removeProviderToken;
|
|
654
|
-
this.
|
|
926
|
+
this.indexedDBStorage = new IndexedDBStorage;
|
|
655
927
|
this.cleanupExpiredPendingAuths();
|
|
656
928
|
}
|
|
657
929
|
async initiateFlow(provider, config, returnUrl) {
|
|
@@ -669,13 +941,10 @@ class OAuthManager {
|
|
|
669
941
|
};
|
|
670
942
|
this.pendingAuths.set(state, pendingAuth);
|
|
671
943
|
this.savePendingAuthToStorage(state, pendingAuth);
|
|
672
|
-
console.log("[OAuth] Requesting authorization URL, flow mode:", this.flowConfig.mode);
|
|
673
944
|
const authUrl = await this.getAuthorizationUrl(provider, state, codeChallenge, config.redirectUri, codeVerifier);
|
|
674
|
-
console.log("[OAuth] Received authorization URL, length:", authUrl?.length);
|
|
675
945
|
if (!authUrl || authUrl.trim() === "") {
|
|
676
946
|
throw new Error("Received empty authorization URL from server");
|
|
677
947
|
}
|
|
678
|
-
console.log("[OAuth] Opening authorization URL, mode:", this.flowConfig.mode);
|
|
679
948
|
if (this.flowConfig.mode === "popup") {
|
|
680
949
|
this.windowManager.openPopup(authUrl, this.flowConfig.popupOptions);
|
|
681
950
|
try {
|
|
@@ -686,7 +955,6 @@ class OAuthManager {
|
|
|
686
955
|
throw error;
|
|
687
956
|
}
|
|
688
957
|
} else {
|
|
689
|
-
console.log("[OAuth] Redirecting to authorization URL:", authUrl.substring(0, 100) + (authUrl.length > 100 ? "..." : ""));
|
|
690
958
|
this.windowManager.openRedirect(authUrl);
|
|
691
959
|
}
|
|
692
960
|
}
|
|
@@ -713,8 +981,12 @@ class OAuthManager {
|
|
|
713
981
|
expiresAt: tokenData.expiresAt,
|
|
714
982
|
scopes: tokenData.scopes
|
|
715
983
|
};
|
|
984
|
+
const email = await fetchUserEmail(provider, tokenDataToStore);
|
|
985
|
+
if (email) {
|
|
986
|
+
tokenDataToStore.email = email;
|
|
987
|
+
}
|
|
716
988
|
this.providerTokens.set(provider, tokenDataToStore);
|
|
717
|
-
await this.saveProviderToken(provider, tokenDataToStore);
|
|
989
|
+
await this.saveProviderToken(provider, tokenDataToStore, email);
|
|
718
990
|
this.pendingAuths.delete(state);
|
|
719
991
|
this.removePendingAuthFromStorage(state);
|
|
720
992
|
return { ...tokenDataToStore, provider };
|
|
@@ -750,8 +1022,12 @@ class OAuthManager {
|
|
|
750
1022
|
expiresAt: response.expiresAt,
|
|
751
1023
|
scopes: response.scopes
|
|
752
1024
|
};
|
|
1025
|
+
const email = await fetchUserEmail(pendingAuth.provider, tokenData);
|
|
1026
|
+
if (email) {
|
|
1027
|
+
tokenData.email = email;
|
|
1028
|
+
}
|
|
753
1029
|
this.providerTokens.set(pendingAuth.provider, tokenData);
|
|
754
|
-
await this.saveProviderToken(pendingAuth.provider, tokenData);
|
|
1030
|
+
await this.saveProviderToken(pendingAuth.provider, tokenData, email);
|
|
755
1031
|
this.pendingAuths.delete(state);
|
|
756
1032
|
this.removePendingAuthFromStorage(state);
|
|
757
1033
|
return { ...tokenData, provider: pendingAuth.provider };
|
|
@@ -761,8 +1037,8 @@ class OAuthManager {
|
|
|
761
1037
|
throw error;
|
|
762
1038
|
}
|
|
763
1039
|
}
|
|
764
|
-
async checkAuthStatus(provider) {
|
|
765
|
-
const tokenData = await this.getProviderToken(provider);
|
|
1040
|
+
async checkAuthStatus(provider, email) {
|
|
1041
|
+
const tokenData = await this.getProviderToken(provider, email);
|
|
766
1042
|
if (!tokenData) {
|
|
767
1043
|
return {
|
|
768
1044
|
authorized: false,
|
|
@@ -776,30 +1052,83 @@ class OAuthManager {
|
|
|
776
1052
|
expiresAt: tokenData.expiresAt
|
|
777
1053
|
};
|
|
778
1054
|
}
|
|
1055
|
+
async disconnectAccount(provider, email, context) {
|
|
1056
|
+
if (this.removeTokenCallback) {
|
|
1057
|
+
try {
|
|
1058
|
+
await this.removeTokenCallback(provider, email, context);
|
|
1059
|
+
} catch (error) {
|
|
1060
|
+
console.error(`Failed to delete token for ${provider} (${email}) from database:`, error);
|
|
1061
|
+
}
|
|
1062
|
+
} else if (this.setTokenCallback) {
|
|
1063
|
+
try {
|
|
1064
|
+
await this.setTokenCallback(provider, null, email, context);
|
|
1065
|
+
} catch (error) {
|
|
1066
|
+
console.error(`Failed to delete token for ${provider} (${email}) from database:`, error);
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
if (!this.setTokenCallback && !this.removeTokenCallback) {
|
|
1070
|
+
try {
|
|
1071
|
+
await this.indexedDBStorage.deleteToken(provider, email);
|
|
1072
|
+
} catch (error) {
|
|
1073
|
+
console.error(`Failed to delete token from IndexedDB for ${provider} (${email}):`, error);
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
this.providerTokens.delete(provider);
|
|
1077
|
+
}
|
|
779
1078
|
async disconnectProvider(provider, context) {
|
|
780
1079
|
if (this.removeTokenCallback) {
|
|
781
1080
|
try {
|
|
782
|
-
await this.removeTokenCallback(provider, context);
|
|
1081
|
+
await this.removeTokenCallback(provider, undefined, context);
|
|
783
1082
|
} catch (error) {
|
|
784
|
-
console.error(`Failed to delete
|
|
1083
|
+
console.error(`Failed to delete tokens for ${provider} from database:`, error);
|
|
785
1084
|
}
|
|
786
1085
|
} else if (this.setTokenCallback) {
|
|
787
1086
|
try {
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
1087
|
+
await this.setTokenCallback(provider, null, undefined, context);
|
|
1088
|
+
} catch (error) {
|
|
1089
|
+
console.error(`Failed to delete tokens for ${provider} from database:`, error);
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
if (!this.setTokenCallback && !this.removeTokenCallback) {
|
|
1093
|
+
try {
|
|
1094
|
+
await this.indexedDBStorage.deleteTokensByProvider(provider);
|
|
792
1095
|
} catch (error) {
|
|
793
|
-
|
|
1096
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
1097
|
+
try {
|
|
1098
|
+
const key = `integrate_token_${provider}`;
|
|
1099
|
+
window.localStorage.removeItem(key);
|
|
1100
|
+
} catch (localStorageError) {}
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
if (!this.setTokenCallback && !this.removeTokenCallback) {
|
|
1105
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
1106
|
+
try {
|
|
1107
|
+
const key = `integrate_token_${provider}`;
|
|
1108
|
+
window.localStorage.removeItem(key);
|
|
1109
|
+
} catch (localStorageError) {}
|
|
794
1110
|
}
|
|
795
1111
|
}
|
|
796
1112
|
this.providerTokens.delete(provider);
|
|
797
|
-
this.clearProviderToken(provider);
|
|
798
1113
|
}
|
|
799
|
-
async
|
|
1114
|
+
async listAccounts(provider) {
|
|
1115
|
+
if (this.getTokenCallback) {
|
|
1116
|
+
return [];
|
|
1117
|
+
}
|
|
1118
|
+
if (!this.getTokenCallback) {
|
|
1119
|
+
try {
|
|
1120
|
+
return await this.indexedDBStorage.listAccounts(provider);
|
|
1121
|
+
} catch (error) {
|
|
1122
|
+
console.error(`Failed to list accounts for ${provider}:`, error);
|
|
1123
|
+
return [];
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
return [];
|
|
1127
|
+
}
|
|
1128
|
+
async getProviderToken(provider, email, context) {
|
|
800
1129
|
if (this.getTokenCallback) {
|
|
801
1130
|
try {
|
|
802
|
-
const tokenData = await this.getTokenCallback(provider, context);
|
|
1131
|
+
const tokenData = await this.getTokenCallback(provider, email, context);
|
|
803
1132
|
if (tokenData) {
|
|
804
1133
|
this.providerTokens.set(provider, tokenData);
|
|
805
1134
|
}
|
|
@@ -809,6 +1138,17 @@ class OAuthManager {
|
|
|
809
1138
|
return;
|
|
810
1139
|
}
|
|
811
1140
|
}
|
|
1141
|
+
if (email && !this.getTokenCallback) {
|
|
1142
|
+
try {
|
|
1143
|
+
const tokenData = await this.indexedDBStorage.getToken(provider, email);
|
|
1144
|
+
if (tokenData) {
|
|
1145
|
+
this.providerTokens.set(provider, tokenData);
|
|
1146
|
+
}
|
|
1147
|
+
return tokenData;
|
|
1148
|
+
} catch (error) {
|
|
1149
|
+
console.error(`Failed to get token from IndexedDB for ${provider}:`, error);
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
812
1152
|
return this.providerTokens.get(provider);
|
|
813
1153
|
}
|
|
814
1154
|
getAllProviderTokens() {
|
|
@@ -817,35 +1157,45 @@ class OAuthManager {
|
|
|
817
1157
|
getProviderTokenFromCache(provider) {
|
|
818
1158
|
return this.providerTokens.get(provider);
|
|
819
1159
|
}
|
|
820
|
-
async setProviderToken(provider, tokenData, context) {
|
|
1160
|
+
async setProviderToken(provider, tokenData, email, context) {
|
|
1161
|
+
const tokenEmail = email || tokenData?.email;
|
|
821
1162
|
if (tokenData === null) {
|
|
822
|
-
|
|
1163
|
+
if (tokenEmail) {
|
|
1164
|
+
this.providerTokens.delete(provider);
|
|
1165
|
+
} else {
|
|
1166
|
+
this.providerTokens.delete(provider);
|
|
1167
|
+
}
|
|
823
1168
|
} else {
|
|
824
1169
|
this.providerTokens.set(provider, tokenData);
|
|
825
1170
|
}
|
|
826
|
-
await this.saveProviderToken(provider, tokenData, context);
|
|
1171
|
+
await this.saveProviderToken(provider, tokenData, tokenEmail, context);
|
|
827
1172
|
}
|
|
828
1173
|
clearProviderToken(provider) {
|
|
829
1174
|
this.providerTokens.delete(provider);
|
|
830
|
-
if (!this.
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
}
|
|
834
|
-
console.error(`Failed to clear token for ${provider} from localStorage:`, error);
|
|
835
|
-
}
|
|
1175
|
+
if (!this.setTokenCallback && !this.removeTokenCallback && !this.skipLocalStorage) {
|
|
1176
|
+
this.indexedDBStorage.deleteTokensByProvider(provider).catch((error) => {
|
|
1177
|
+
console.error(`Failed to clear tokens for ${provider} from IndexedDB:`, error);
|
|
1178
|
+
});
|
|
836
1179
|
}
|
|
837
1180
|
}
|
|
838
1181
|
clearAllProviderTokens() {
|
|
839
|
-
const providers = Array.from(this.providerTokens.keys());
|
|
840
1182
|
this.providerTokens.clear();
|
|
841
|
-
if (!this.
|
|
842
|
-
|
|
1183
|
+
if (!this.setTokenCallback && !this.removeTokenCallback && !this.skipLocalStorage) {
|
|
1184
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
843
1185
|
try {
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
1186
|
+
const keysToRemove = [];
|
|
1187
|
+
for (let i = 0;i < window.localStorage.length; i++) {
|
|
1188
|
+
const key = window.localStorage.key(i);
|
|
1189
|
+
if (key && key.startsWith("integrate_token_")) {
|
|
1190
|
+
keysToRemove.push(key);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
keysToRemove.forEach((key) => window.localStorage.removeItem(key));
|
|
1194
|
+
} catch (localStorageError) {}
|
|
848
1195
|
}
|
|
1196
|
+
this.indexedDBStorage.clearAll().catch((error) => {
|
|
1197
|
+
console.error("Failed to clear all tokens from IndexedDB:", error);
|
|
1198
|
+
});
|
|
849
1199
|
}
|
|
850
1200
|
}
|
|
851
1201
|
clearAllPendingAuths() {
|
|
@@ -866,67 +1216,125 @@ class OAuthManager {
|
|
|
866
1216
|
}
|
|
867
1217
|
}
|
|
868
1218
|
}
|
|
869
|
-
async saveProviderToken(provider, tokenData, context) {
|
|
1219
|
+
async saveProviderToken(provider, tokenData, email, context) {
|
|
870
1220
|
if (this.setTokenCallback) {
|
|
871
1221
|
try {
|
|
872
|
-
await this.setTokenCallback(provider, tokenData, context);
|
|
1222
|
+
await this.setTokenCallback(provider, tokenData, email, context);
|
|
873
1223
|
} catch (error) {
|
|
874
1224
|
console.error(`Failed to ${tokenData === null ? "delete" : "save"} token for ${provider} via callback:`, error);
|
|
875
1225
|
throw error;
|
|
876
1226
|
}
|
|
877
1227
|
return;
|
|
878
1228
|
}
|
|
879
|
-
if (
|
|
880
|
-
this.clearProviderToken(provider);
|
|
1229
|
+
if (this.skipLocalStorage) {
|
|
881
1230
|
return;
|
|
882
1231
|
}
|
|
883
|
-
if (
|
|
884
|
-
|
|
1232
|
+
if (tokenData === null) {
|
|
1233
|
+
if (email) {
|
|
1234
|
+
if (!this.setTokenCallback && !this.removeTokenCallback) {
|
|
1235
|
+
await this.indexedDBStorage.deleteToken(provider, email).catch(() => {
|
|
1236
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
1237
|
+
try {
|
|
1238
|
+
const key = `integrate_token_${provider}`;
|
|
1239
|
+
window.localStorage.removeItem(key);
|
|
1240
|
+
} catch (localStorageError) {}
|
|
1241
|
+
}
|
|
1242
|
+
});
|
|
1243
|
+
}
|
|
1244
|
+
} else {
|
|
1245
|
+
this.clearProviderToken(provider);
|
|
1246
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
1247
|
+
try {
|
|
1248
|
+
const key = `integrate_token_${provider}`;
|
|
1249
|
+
window.localStorage.removeItem(key);
|
|
1250
|
+
} catch (localStorageError) {}
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
885
1253
|
return;
|
|
886
1254
|
}
|
|
887
|
-
|
|
1255
|
+
const tokenEmail = email || tokenData.email;
|
|
1256
|
+
if (tokenEmail) {
|
|
888
1257
|
try {
|
|
889
|
-
|
|
890
|
-
window.localStorage.setItem(key, JSON.stringify(tokenData));
|
|
1258
|
+
await this.indexedDBStorage.saveToken(provider, tokenEmail, tokenData);
|
|
891
1259
|
} catch (error) {
|
|
892
|
-
|
|
1260
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
1261
|
+
try {
|
|
1262
|
+
const key = `integrate_token_${provider}`;
|
|
1263
|
+
window.localStorage.setItem(key, JSON.stringify(tokenData));
|
|
1264
|
+
} catch (localStorageError) {
|
|
1265
|
+
console.error(`Failed to save token for ${provider} to localStorage:`, localStorageError);
|
|
1266
|
+
}
|
|
1267
|
+
} else {
|
|
1268
|
+
console.error(`Failed to save token for ${provider} to IndexedDB:`, error);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
} else {
|
|
1272
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
1273
|
+
try {
|
|
1274
|
+
const key = `integrate_token_${provider}`;
|
|
1275
|
+
window.localStorage.setItem(key, JSON.stringify(tokenData));
|
|
1276
|
+
} catch (localStorageError) {
|
|
1277
|
+
console.error(`Failed to save token for ${provider} to localStorage:`, localStorageError);
|
|
1278
|
+
}
|
|
893
1279
|
}
|
|
894
1280
|
}
|
|
895
1281
|
}
|
|
896
|
-
async loadProviderToken(provider) {
|
|
1282
|
+
async loadProviderToken(provider, email, context) {
|
|
897
1283
|
if (this.getTokenCallback) {
|
|
898
1284
|
try {
|
|
899
|
-
return await this.getTokenCallback(provider);
|
|
1285
|
+
return await this.getTokenCallback(provider, email, context);
|
|
900
1286
|
} catch (error) {
|
|
901
1287
|
console.error(`Failed to load token for ${provider} via callback:`, error);
|
|
902
1288
|
return;
|
|
903
1289
|
}
|
|
904
1290
|
}
|
|
905
1291
|
if (this.skipLocalStorage) {
|
|
906
|
-
return;
|
|
1292
|
+
return this.providerTokens.get(provider);
|
|
907
1293
|
}
|
|
908
|
-
if (
|
|
1294
|
+
if (email) {
|
|
909
1295
|
try {
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
if (
|
|
913
|
-
|
|
1296
|
+
return await this.indexedDBStorage.getToken(provider, email);
|
|
1297
|
+
} catch (error) {
|
|
1298
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
1299
|
+
try {
|
|
1300
|
+
const key = `integrate_token_${provider}`;
|
|
1301
|
+
const stored = window.localStorage.getItem(key);
|
|
1302
|
+
if (stored) {
|
|
1303
|
+
return JSON.parse(stored);
|
|
1304
|
+
}
|
|
1305
|
+
} catch (localStorageError) {}
|
|
1306
|
+
}
|
|
1307
|
+
return;
|
|
1308
|
+
}
|
|
1309
|
+
} else {
|
|
1310
|
+
try {
|
|
1311
|
+
const tokens = await this.indexedDBStorage.getTokensByProvider(provider);
|
|
1312
|
+
if (tokens.size > 0) {
|
|
1313
|
+
return tokens.values().next().value;
|
|
914
1314
|
}
|
|
915
1315
|
} catch (error) {
|
|
916
|
-
|
|
1316
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
1317
|
+
try {
|
|
1318
|
+
const key = `integrate_token_${provider}`;
|
|
1319
|
+
const stored = window.localStorage.getItem(key);
|
|
1320
|
+
if (stored) {
|
|
1321
|
+
return JSON.parse(stored);
|
|
1322
|
+
}
|
|
1323
|
+
} catch (localStorageError) {}
|
|
1324
|
+
}
|
|
917
1325
|
}
|
|
918
1326
|
}
|
|
919
1327
|
return;
|
|
920
1328
|
}
|
|
921
1329
|
async loadAllProviderTokens(providers) {
|
|
922
1330
|
for (const provider of providers) {
|
|
923
|
-
const tokenData = await this.loadProviderToken(provider);
|
|
1331
|
+
const tokenData = await this.loadProviderToken(provider, undefined, undefined);
|
|
924
1332
|
if (tokenData) {
|
|
925
1333
|
this.providerTokens.set(provider, tokenData);
|
|
926
1334
|
}
|
|
927
1335
|
}
|
|
928
1336
|
}
|
|
929
|
-
|
|
1337
|
+
loadAllProviderTokensSync(providers) {
|
|
930
1338
|
if (this.getTokenCallback) {
|
|
931
1339
|
return;
|
|
932
1340
|
}
|
|
@@ -934,33 +1342,20 @@ class OAuthManager {
|
|
|
934
1342
|
return;
|
|
935
1343
|
}
|
|
936
1344
|
if (typeof window !== "undefined" && window.localStorage) {
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
}
|
|
947
|
-
return;
|
|
948
|
-
}
|
|
949
|
-
loadAllProviderTokensSync(providers) {
|
|
950
|
-
if (this.getTokenCallback) {
|
|
951
|
-
return;
|
|
952
|
-
}
|
|
953
|
-
for (const provider of providers) {
|
|
954
|
-
const tokenData = this.loadProviderTokenSync(provider);
|
|
955
|
-
if (tokenData) {
|
|
956
|
-
this.providerTokens.set(provider, tokenData);
|
|
1345
|
+
for (const provider of providers) {
|
|
1346
|
+
try {
|
|
1347
|
+
const key = `integrate_token_${provider}`;
|
|
1348
|
+
const stored = window.localStorage.getItem(key);
|
|
1349
|
+
if (stored) {
|
|
1350
|
+
const tokenData = JSON.parse(stored);
|
|
1351
|
+
this.providerTokens.set(provider, tokenData);
|
|
1352
|
+
}
|
|
1353
|
+
} catch {}
|
|
957
1354
|
}
|
|
958
1355
|
}
|
|
1356
|
+
this.loadAllProviderTokens(providers).catch(() => {});
|
|
959
1357
|
}
|
|
960
1358
|
savePendingAuthToStorage(state, pendingAuth) {
|
|
961
|
-
if (this.skipLocalStorage) {
|
|
962
|
-
return;
|
|
963
|
-
}
|
|
964
1359
|
if (typeof window !== "undefined" && window.localStorage) {
|
|
965
1360
|
try {
|
|
966
1361
|
const key = `integrate_oauth_pending_${state}`;
|
|
@@ -971,9 +1366,6 @@ class OAuthManager {
|
|
|
971
1366
|
}
|
|
972
1367
|
}
|
|
973
1368
|
loadPendingAuthFromStorage(state) {
|
|
974
|
-
if (this.skipLocalStorage) {
|
|
975
|
-
return;
|
|
976
|
-
}
|
|
977
1369
|
if (typeof window !== "undefined" && window.localStorage) {
|
|
978
1370
|
try {
|
|
979
1371
|
const key = `integrate_oauth_pending_${state}`;
|
|
@@ -988,9 +1380,6 @@ class OAuthManager {
|
|
|
988
1380
|
return;
|
|
989
1381
|
}
|
|
990
1382
|
removePendingAuthFromStorage(state) {
|
|
991
|
-
if (this.skipLocalStorage) {
|
|
992
|
-
return;
|
|
993
|
-
}
|
|
994
1383
|
if (typeof window !== "undefined" && window.localStorage) {
|
|
995
1384
|
try {
|
|
996
1385
|
const key = `integrate_oauth_pending_${state}`;
|
|
@@ -1001,9 +1390,6 @@ class OAuthManager {
|
|
|
1001
1390
|
}
|
|
1002
1391
|
}
|
|
1003
1392
|
cleanupExpiredPendingAuths() {
|
|
1004
|
-
if (this.skipLocalStorage) {
|
|
1005
|
-
return;
|
|
1006
|
-
}
|
|
1007
1393
|
if (typeof window !== "undefined" && window.localStorage) {
|
|
1008
1394
|
try {
|
|
1009
1395
|
const prefix = "integrate_oauth_pending_";
|
|
@@ -1050,7 +1436,7 @@ class OAuthManager {
|
|
|
1050
1436
|
})
|
|
1051
1437
|
});
|
|
1052
1438
|
if (response.headers.get("X-Integrate-Use-Database") === "true") {
|
|
1053
|
-
this.
|
|
1439
|
+
this.setSkipLocalStorage(true);
|
|
1054
1440
|
}
|
|
1055
1441
|
if (!response.ok) {
|
|
1056
1442
|
const error = await response.text();
|
|
@@ -1058,15 +1444,11 @@ class OAuthManager {
|
|
|
1058
1444
|
}
|
|
1059
1445
|
const data = await response.json();
|
|
1060
1446
|
if (!data.authorizationUrl) {
|
|
1061
|
-
console.error("[OAuth] Authorization URL is missing from response:", data);
|
|
1062
1447
|
throw new Error("Authorization URL is missing from server response");
|
|
1063
1448
|
}
|
|
1064
1449
|
if (typeof data.authorizationUrl !== "string" || data.authorizationUrl.trim() === "") {
|
|
1065
|
-
console.error("[OAuth] Invalid authorization URL received:", data.authorizationUrl);
|
|
1066
1450
|
throw new Error("Invalid authorization URL received from server");
|
|
1067
1451
|
}
|
|
1068
|
-
const urlPreview = data.authorizationUrl.length > 100 ? data.authorizationUrl.substring(0, 100) + "..." : data.authorizationUrl;
|
|
1069
|
-
console.log("[OAuth] Received authorization URL from API route:", urlPreview);
|
|
1070
1452
|
return data.authorizationUrl;
|
|
1071
1453
|
}
|
|
1072
1454
|
async exchangeCodeForToken(provider, code, codeVerifier, state) {
|
|
@@ -1084,7 +1466,7 @@ class OAuthManager {
|
|
|
1084
1466
|
})
|
|
1085
1467
|
});
|
|
1086
1468
|
if (response.headers.get("X-Integrate-Use-Database") === "true") {
|
|
1087
|
-
this.
|
|
1469
|
+
this.setSkipLocalStorage(true);
|
|
1088
1470
|
}
|
|
1089
1471
|
if (!response.ok) {
|
|
1090
1472
|
const error = await response.text();
|
|
@@ -1353,7 +1735,7 @@ class MCPClientBase {
|
|
|
1353
1735
|
const hasApiKey = !!transportHeaders["X-API-KEY"];
|
|
1354
1736
|
if (hasApiKey) {
|
|
1355
1737
|
if (provider) {
|
|
1356
|
-
const tokenData = await this.oauthManager.getProviderToken(provider, options?.context);
|
|
1738
|
+
const tokenData = await this.oauthManager.getProviderToken(provider, undefined, options?.context);
|
|
1357
1739
|
if (tokenData && this.transport.setHeader) {
|
|
1358
1740
|
const previousAuthHeader = transportHeaders["Authorization"];
|
|
1359
1741
|
try {
|
|
@@ -1383,7 +1765,7 @@ class MCPClientBase {
|
|
|
1383
1765
|
"Content-Type": "application/json"
|
|
1384
1766
|
};
|
|
1385
1767
|
if (provider) {
|
|
1386
|
-
const tokenData = await this.oauthManager.getProviderToken(provider, options?.context);
|
|
1768
|
+
const tokenData = await this.oauthManager.getProviderToken(provider, undefined, options?.context);
|
|
1387
1769
|
if (tokenData) {
|
|
1388
1770
|
headers["Authorization"] = `Bearer ${tokenData.accessToken}`;
|
|
1389
1771
|
}
|
|
@@ -1527,6 +1909,29 @@ class MCPClientBase {
|
|
|
1527
1909
|
throw error;
|
|
1528
1910
|
}
|
|
1529
1911
|
}
|
|
1912
|
+
async disconnectAccount(provider, email, context) {
|
|
1913
|
+
const integration = this.integrations.find((p) => p.oauth?.provider === provider);
|
|
1914
|
+
if (!integration?.oauth) {
|
|
1915
|
+
throw new Error(`No OAuth configuration found for provider: ${provider}`);
|
|
1916
|
+
}
|
|
1917
|
+
try {
|
|
1918
|
+
await this.oauthManager.disconnectAccount(provider, email, context);
|
|
1919
|
+
const accounts = await this.oauthManager.listAccounts(provider);
|
|
1920
|
+
if (accounts.length === 0) {
|
|
1921
|
+
this.authState.set(provider, { authenticated: false });
|
|
1922
|
+
}
|
|
1923
|
+
this.eventEmitter.emit("auth:disconnect", { provider });
|
|
1924
|
+
} catch (error) {
|
|
1925
|
+
this.eventEmitter.emit("auth:error", {
|
|
1926
|
+
provider,
|
|
1927
|
+
error
|
|
1928
|
+
});
|
|
1929
|
+
throw error;
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
async listAccounts(provider) {
|
|
1933
|
+
return await this.oauthManager.listAccounts(provider);
|
|
1934
|
+
}
|
|
1530
1935
|
async logout() {
|
|
1531
1936
|
this.clearSessionToken();
|
|
1532
1937
|
this.oauthManager.clearAllPendingAuths();
|
|
@@ -1559,13 +1964,13 @@ class MCPClientBase {
|
|
|
1559
1964
|
isProviderAuthenticated(provider) {
|
|
1560
1965
|
return this.authState.get(provider)?.authenticated ?? false;
|
|
1561
1966
|
}
|
|
1562
|
-
async isAuthorized(provider, context) {
|
|
1967
|
+
async isAuthorized(provider, email, context) {
|
|
1563
1968
|
if (this.oauthCallbackPromise) {
|
|
1564
1969
|
await this.oauthCallbackPromise;
|
|
1565
1970
|
this.oauthCallbackPromise = null;
|
|
1566
1971
|
}
|
|
1567
1972
|
try {
|
|
1568
|
-
const tokenData = await this.oauthManager.getProviderToken(provider, context);
|
|
1973
|
+
const tokenData = await this.oauthManager.getProviderToken(provider, email, context);
|
|
1569
1974
|
const isAuthenticated = !!tokenData;
|
|
1570
1975
|
const currentState = this.authState.get(provider);
|
|
1571
1976
|
if (currentState) {
|
|
@@ -1603,8 +2008,8 @@ class MCPClientBase {
|
|
|
1603
2008
|
}
|
|
1604
2009
|
return authorized;
|
|
1605
2010
|
}
|
|
1606
|
-
async getAuthorizationStatus(provider) {
|
|
1607
|
-
return await this.oauthManager.checkAuthStatus(provider);
|
|
2011
|
+
async getAuthorizationStatus(provider, email) {
|
|
2012
|
+
return await this.oauthManager.checkAuthStatus(provider, email);
|
|
1608
2013
|
}
|
|
1609
2014
|
async authorize(provider, options) {
|
|
1610
2015
|
const integration = this.integrations.find((p) => p.oauth?.provider === provider);
|
|
@@ -1662,11 +2067,11 @@ class MCPClientBase {
|
|
|
1662
2067
|
throw error;
|
|
1663
2068
|
}
|
|
1664
2069
|
}
|
|
1665
|
-
async getProviderToken(provider, context) {
|
|
1666
|
-
return await this.oauthManager.getProviderToken(provider, context);
|
|
2070
|
+
async getProviderToken(provider, email, context) {
|
|
2071
|
+
return await this.oauthManager.getProviderToken(provider, email, context);
|
|
1667
2072
|
}
|
|
1668
|
-
async setProviderToken(provider, tokenData, context) {
|
|
1669
|
-
await this.oauthManager.setProviderToken(provider, tokenData, context);
|
|
2073
|
+
async setProviderToken(provider, tokenData, email, context) {
|
|
2074
|
+
await this.oauthManager.setProviderToken(provider, tokenData, email, context);
|
|
1670
2075
|
if (tokenData === null) {
|
|
1671
2076
|
this.authState.set(provider, { authenticated: false });
|
|
1672
2077
|
} else {
|
|
@@ -6708,7 +7113,6 @@ function createMCPServer(config) {
|
|
|
6708
7113
|
}
|
|
6709
7114
|
}
|
|
6710
7115
|
if (!targetOrigin) {
|
|
6711
|
-
console.warn("[OAuth] Could not determine frontend origin for redirect. Using request origin as fallback.");
|
|
6712
7116
|
targetOrigin = new URL(webRequest.url).origin;
|
|
6713
7117
|
}
|
|
6714
7118
|
const targetUrl = new URL(returnUrl, targetOrigin);
|
|
@@ -7252,7 +7656,6 @@ class OAuthHandler {
|
|
|
7252
7656
|
} else {
|
|
7253
7657
|
authorizeRequest = request;
|
|
7254
7658
|
}
|
|
7255
|
-
console.log("[handleAuthorize] Received request for provider:", authorizeRequest.provider, "has codeVerifier:", !!authorizeRequest.codeVerifier, "has frontendOrigin:", !!authorizeRequest.frontendOrigin);
|
|
7256
7659
|
const providerConfig = this.config.providers[authorizeRequest.provider];
|
|
7257
7660
|
if (!providerConfig) {
|
|
7258
7661
|
throw new Error(`Provider ${authorizeRequest.provider} not configured. Add OAuth credentials to your API route configuration.`);
|
|
@@ -7293,22 +7696,14 @@ class OAuthHandler {
|
|
|
7293
7696
|
const data = await response.json();
|
|
7294
7697
|
const result = data;
|
|
7295
7698
|
if (!result.authorizationUrl) {
|
|
7296
|
-
console.error("[OAuth] MCP server did not return authorizationUrl:", data);
|
|
7297
7699
|
throw new Error("MCP server failed to return authorization URL");
|
|
7298
7700
|
}
|
|
7299
|
-
const urlPreview = result.authorizationUrl.length > 100 ? result.authorizationUrl.substring(0, 100) + "..." : result.authorizationUrl;
|
|
7300
|
-
console.log("[OAuth] Generated authorization URL:", urlPreview);
|
|
7301
7701
|
if (authorizeRequest.codeVerifier) {
|
|
7302
7702
|
try {
|
|
7303
7703
|
const { storeCodeVerifier: storeCodeVerifier2 } = await Promise.resolve().then(() => (init_server(), exports_server));
|
|
7304
7704
|
storeCodeVerifier2(authorizeRequest.state, authorizeRequest.codeVerifier, authorizeRequest.provider, authorizeRequest.frontendOrigin);
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
console.warn("[OAuth] Failed to store codeVerifier:", error);
|
|
7308
|
-
}
|
|
7309
|
-
} else {
|
|
7310
|
-
console.log("[OAuth] No codeVerifier provided in authorize request");
|
|
7311
|
-
}
|
|
7705
|
+
} catch (error) {}
|
|
7706
|
+
} else {}
|
|
7312
7707
|
if (webRequest) {
|
|
7313
7708
|
try {
|
|
7314
7709
|
const { detectSessionContext: detectSessionContext2 } = await Promise.resolve().then(() => exports_session_detector);
|
|
@@ -7325,9 +7720,7 @@ class OAuthHandler {
|
|
|
7325
7720
|
const cookieValue = await createContextCookie2(context, authorizeRequest.provider, secret);
|
|
7326
7721
|
result.setCookie = getSetCookieHeader2(cookieValue);
|
|
7327
7722
|
}
|
|
7328
|
-
} catch (error) {
|
|
7329
|
-
console.warn("[OAuth] Failed to capture user context:", error);
|
|
7330
|
-
}
|
|
7723
|
+
} catch (error) {}
|
|
7331
7724
|
}
|
|
7332
7725
|
return result;
|
|
7333
7726
|
}
|
|
@@ -7361,9 +7754,7 @@ class OAuthHandler {
|
|
|
7361
7754
|
context = contextData.context;
|
|
7362
7755
|
}
|
|
7363
7756
|
}
|
|
7364
|
-
} catch (error) {
|
|
7365
|
-
console.warn("[OAuth] Failed to restore user context:", error);
|
|
7366
|
-
}
|
|
7757
|
+
} catch (error) {}
|
|
7367
7758
|
}
|
|
7368
7759
|
const url = new URL("/oauth/callback", this.serverUrl);
|
|
7369
7760
|
const response = await fetch(url.toString(), {
|
|
@@ -7397,10 +7788,8 @@ class OAuthHandler {
|
|
|
7397
7788
|
expiresAt: result.expiresAt,
|
|
7398
7789
|
scopes: result.scopes
|
|
7399
7790
|
};
|
|
7400
|
-
await this.config.setProviderToken(callbackRequest.provider, tokenData, context);
|
|
7401
|
-
} catch (error) {
|
|
7402
|
-
console.error("[OAuth] Failed to save provider token:", error);
|
|
7403
|
-
}
|
|
7791
|
+
await this.config.setProviderToken(callbackRequest.provider, tokenData, undefined, context);
|
|
7792
|
+
} catch (error) {}
|
|
7404
7793
|
}
|
|
7405
7794
|
if (webRequest) {
|
|
7406
7795
|
const { getClearCookieHeader: getClearCookieHeader2 } = await Promise.resolve().then(() => exports_context_cookie);
|
|
@@ -7445,7 +7834,7 @@ class OAuthHandler {
|
|
|
7445
7834
|
}
|
|
7446
7835
|
if (context) {
|
|
7447
7836
|
try {
|
|
7448
|
-
await this.config.removeProviderToken(request.provider, context);
|
|
7837
|
+
await this.config.removeProviderToken(request.provider, undefined, context);
|
|
7449
7838
|
} catch (error) {
|
|
7450
7839
|
console.error(`Failed to delete token for ${request.provider} from database via removeProviderToken:`, error);
|
|
7451
7840
|
}
|