Add OAuth login support and streamline authentication flows
- Introduced `oauthLogin` method in `electron/preload.ts` and backend IPC handlers for OAuth via `BrowserWindow`. - Replaced web-based OAuth redirection with Electron-specific implementation for Google, Facebook, and Apple. - Refactored `SocialForm.tsx` to handle OAuth login success and token management via Electron. - Updated `User`, `QuillSense`, and context methods to include `quill-trial` subscriptions and extended login logic. - Cleaned up code, removed unused imports, and improved error handling for authentication scenarios.
This commit is contained in:
108
electron/main.ts
108
electron/main.ts
@@ -188,6 +188,114 @@ ipcMain.handle('open-external', async (_event, url: string) => {
|
||||
}
|
||||
});
|
||||
|
||||
// IPC Handler pour OAuth login via BrowserWindow
|
||||
let oauthWindow: BrowserWindow | null = null;
|
||||
|
||||
interface OAuthResult {
|
||||
success: boolean;
|
||||
code?: string;
|
||||
state?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
interface OAuthRequest {
|
||||
provider: 'google' | 'facebook' | 'apple';
|
||||
baseUrl: string;
|
||||
}
|
||||
|
||||
ipcMain.handle('oauth-login', async (_event, request: OAuthRequest): Promise<OAuthResult> => {
|
||||
return new Promise((resolve) => {
|
||||
const { provider, baseUrl } = request;
|
||||
const redirectUri = `${baseUrl}login?provider=${provider}`;
|
||||
const encodedRedirectUri = encodeURIComponent(redirectUri);
|
||||
|
||||
// Fermer une éventuelle fenêtre OAuth existante
|
||||
if (oauthWindow) {
|
||||
oauthWindow.close();
|
||||
oauthWindow = null;
|
||||
}
|
||||
|
||||
// Configuration OAuth par provider
|
||||
const oauthConfigs: Record<string, string> = {
|
||||
google: `https://accounts.google.com/o/oauth2/v2/auth?client_id=911482317931-pvjog1br22r6l8k1afq0ki94em2fsoen.apps.googleusercontent.com&redirect_uri=${encodedRedirectUri}&response_type=code&scope=openid%20email%20profile&access_type=offline`,
|
||||
facebook: `https://www.facebook.com/v18.0/dialog/oauth?client_id=1015270470233591&redirect_uri=${encodedRedirectUri}&scope=email&response_type=code&state=abc123`,
|
||||
apple: `https://appleid.apple.com/auth/authorize?client_id=eritors.apple.login&redirect_uri=${encodedRedirectUri}&response_type=code&scope=email%20name&response_mode=query&state=abc123`
|
||||
};
|
||||
|
||||
const authUrl = oauthConfigs[provider];
|
||||
if (!authUrl) {
|
||||
resolve({ success: false, error: 'Invalid provider' });
|
||||
return;
|
||||
}
|
||||
|
||||
oauthWindow = new BrowserWindow({
|
||||
width: 600,
|
||||
height: 700,
|
||||
show: true,
|
||||
autoHideMenuBar: true,
|
||||
webPreferences: {
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
}
|
||||
});
|
||||
|
||||
// Intercepter les redirections pour capturer le code OAuth
|
||||
const handleNavigation = (url: string): boolean => {
|
||||
try {
|
||||
const parsedUrl = new URL(url);
|
||||
|
||||
// Vérifier si c'est notre redirect URI (compare sans le query string)
|
||||
const baseRedirectUri = `${baseUrl}login`;
|
||||
if (url.startsWith(baseRedirectUri)) {
|
||||
const code = parsedUrl.searchParams.get('code');
|
||||
const state = parsedUrl.searchParams.get('state');
|
||||
const error = parsedUrl.searchParams.get('error');
|
||||
|
||||
if (error) {
|
||||
resolve({ success: false, error });
|
||||
} else if (code) {
|
||||
resolve({ success: true, code, state: state || undefined });
|
||||
} else {
|
||||
resolve({ success: false, error: 'No code received' });
|
||||
}
|
||||
|
||||
if (oauthWindow) {
|
||||
oauthWindow.close();
|
||||
oauthWindow = null;
|
||||
}
|
||||
return true; // Navigation interceptée
|
||||
}
|
||||
} catch (e) {
|
||||
// URL invalide, continuer
|
||||
}
|
||||
return false; // Laisser la navigation continuer
|
||||
};
|
||||
|
||||
// Écouter will-redirect (redirections HTTP)
|
||||
oauthWindow.webContents.on('will-redirect', (event, url) => {
|
||||
if (handleNavigation(url)) {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
// Écouter will-navigate (navigations normales)
|
||||
oauthWindow.webContents.on('will-navigate', (event, url) => {
|
||||
if (handleNavigation(url)) {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
// Gérer la fermeture de la fenêtre par l'utilisateur
|
||||
oauthWindow.on('closed', () => {
|
||||
oauthWindow = null;
|
||||
resolve({ success: false, error: 'Window closed by user' });
|
||||
});
|
||||
|
||||
// Charger l'URL OAuth
|
||||
oauthWindow.loadURL(authUrl);
|
||||
});
|
||||
});
|
||||
|
||||
// IPC Handlers pour la gestion du token (OS-encrypted storage)
|
||||
ipcMain.handle('get-token', () => {
|
||||
const storage:SecureStorage = getSecureStorage();
|
||||
|
||||
Reference in New Issue
Block a user