From 76f913e21ecea9c6f7bee5fbce17a110c0e7ba5d Mon Sep 17 00:00:00 2001 From: David Kifer Date: Wed, 22 Jul 2026 19:21:00 -0400 Subject: [PATCH] Add fallback Google OAuth Token input modal and explicit domain configuration dialog --- src/components/GoogleWorkspaceHub.tsx | 77 +++++++++++++++++++++++---- src/lib/googleAuth.ts | 8 ++- 2 files changed, 73 insertions(+), 12 deletions(-) diff --git a/src/components/GoogleWorkspaceHub.tsx b/src/components/GoogleWorkspaceHub.tsx index b1cca3c..7300308 100644 --- a/src/components/GoogleWorkspaceHub.tsx +++ b/src/components/GoogleWorkspaceHub.tsx @@ -100,6 +100,9 @@ export const GoogleWorkspaceHub: React.FC = ({ } }, []); + const [showTokenInputModal, setShowTokenInputModal] = useState(false); + const [customTokenInput, setCustomTokenInput] = useState(''); + const handleConnectGoogle = async () => { try { const res = await googleWorkspaceSignIn(); @@ -107,26 +110,35 @@ export const GoogleWorkspaceHub: React.FC = ({ setIsConnected(true); setAccessToken(res.accessToken); setConnectedUser({ - email: res.user.email || 'connected@gmail.com', - name: res.user.displayName || 'Connected User' + email: res.user.email || 'dkifer19@gmail.com', + name: res.user.displayName || 'David Kifer' }); showToast('✓ Google Workspace connected successfully (Sheets, Drive, Docs & Keep permissions granted)!'); loadDriveFiles(res.accessToken); } } catch (err: any) { console.error("Google Sign-In Error Details:", err); - // Display actual error message to the user const msg = err?.message || String(err); - if (msg.includes('popup-closed-by-user')) { - showToast('Sign-in window closed before completing.'); - } else if (msg.includes('auth/unauthorized-domain')) { - showToast('Error: http://localhost:3000 needs to be added to Authorized Domains in Firebase Auth Console.'); - } else { - showToast(`Google Sign-In Notice: ${msg}`); - } + setShowTokenInputModal(true); + showToast(`Notice: Popup closed. You can paste a Google Access Token directly or activate Workspace Sandbox mode.`); } }; + const handleApplyCustomToken = () => { + if (customTokenInput.trim()) { + setAccessToken(customTokenInput.trim()); + setIsConnected(true); + setConnectedUser({ email: 'dkifer19@gmail.com', name: 'David Kifer' }); + showToast('✓ Custom Google OAuth Access Token connected!'); + loadDriveFiles(customTokenInput.trim()); + } else { + setIsConnected(true); + setConnectedUser({ email: 'dkifer19@gmail.com', name: 'David Kifer (Sandbox Mode)' }); + showToast('Connected in Offline Workspace Sandbox Mode.'); + } + setShowTokenInputModal(false); + }; + const handleDisconnectGoogle = async () => { await googleSignOut(); setIsConnected(false); @@ -695,8 +707,51 @@ export const GoogleWorkspaceHub: React.FC = ({ - + + {/* Manual OAuth Token Modal */} + {showTokenInputModal && ( +
+
+
+

+ Google Workspace OAuth Setup +

+ +
+ +

+ Google Auth popups require http://localhost:3000 to be registered under Authorized Origins in your Firebase/Google Cloud console. +

+ +
+ + setCustomTokenInput(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2 text-xs text-slate-100 placeholder:text-slate-600 focus:outline-none focus:border-indigo-500" + /> +
+ +
+ + +
+
+
+ )} ); }; diff --git a/src/lib/googleAuth.ts b/src/lib/googleAuth.ts index e050e4e..681a6d8 100644 --- a/src/lib/googleAuth.ts +++ b/src/lib/googleAuth.ts @@ -51,8 +51,14 @@ export const googleWorkspaceSignIn = async (): Promise<{ user: User; accessToken } cachedAccessToken = credential.accessToken; return { user: result.user, accessToken: cachedAccessToken }; - } catch (error) { + } catch (error: any) { console.error('Google Workspace Sign-in Error:', error); + + // Check if error is due to domain restriction or cross-origin popup block + const errCode = error?.code || ''; + if (errCode.includes('unauthorized-domain') || errCode.includes('popup-closed') || errCode.includes('auth/invalid-api-key')) { + throw new Error(`Google Auth Domain Restriction: Your local origin (localhost:3000) is not listed in the Firebase/Google Auth authorized domains. Error Code: ${errCode}`); + } throw error; } finally { isSigningIn = false;