Add fallback Google OAuth Token input modal and explicit domain configuration dialog

This commit is contained in:
2026-07-22 19:21:00 -04:00
parent 2fbf7ecd8b
commit 76f913e21e
2 changed files with 73 additions and 12 deletions
+66 -11
View File
@@ -100,6 +100,9 @@ export const GoogleWorkspaceHub: React.FC<GoogleWorkspaceHubProps> = ({
}
}, []);
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<GoogleWorkspaceHubProps> = ({
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<GoogleWorkspaceHubProps> = ({
</div>
</div>
</div>
</div>
{/* Manual OAuth Token Modal */}
{showTokenInputModal && (
<div className="fixed inset-0 bg-slate-950/80 backdrop-blur-md flex items-center justify-center p-4 z-50 animate-fadeIn">
<div className="bg-slate-900 border border-slate-800 rounded-2xl max-w-md w-full p-6 shadow-2xl space-y-4">
<div className="flex items-center justify-between pb-3 border-b border-slate-800">
<h3 className="text-sm font-bold text-white flex items-center gap-2">
<Lock className="w-4 h-4 text-indigo-400" /> Google Workspace OAuth Setup
</h3>
<button onClick={() => setShowTokenInputModal(false)} className="text-slate-400 hover:text-white text-xs">✕</button>
</div>
<p className="text-xs text-slate-300">
Google Auth popups require <code className="text-indigo-300">http://localhost:3000</code> to be registered under <strong>Authorized Origins</strong> in your Firebase/Google Cloud console.
</p>
<div className="space-y-2">
<label className="text-xs font-semibold text-slate-400 block">Option A: Paste Google OAuth Access Token</label>
<input
type="password"
placeholder="ya29.a0... (Paste OAuth Token)"
value={customTokenInput}
onChange={(e) => 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"
/>
</div>
<div className="flex items-center justify-end gap-2 pt-2">
<button
onClick={() => handleApplyCustomToken()}
className="px-4 py-2 rounded-xl bg-slate-800 hover:bg-slate-700 text-slate-300 text-xs font-semibold"
>
Use Offline Sandbox
</button>
<button
onClick={() => handleApplyCustomToken()}
className="px-4 py-2 rounded-xl bg-indigo-600 hover:bg-indigo-500 text-white text-xs font-bold shadow-lg shadow-indigo-600/30"
>
Connect Token
</button>
</div>
</div>
</div>
)}
</div>
);
};
+7 -1
View File
@@ -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;