First stage of the new flow

This commit is contained in:
Roman Krček
2025-07-02 21:50:45 +02:00
parent 5fd647d894
commit 822f1a7342
15 changed files with 1317 additions and 140 deletions

View File

@@ -0,0 +1,110 @@
import { redirect } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { getOAuthClient } from '$lib/google-server.js';
export const GET: RequestHandler = async ({ url }) => {
try {
const code = url.searchParams.get('code');
const error = url.searchParams.get('error');
if (error) {
console.error('Google OAuth error:', error);
throw redirect(302, '/private/events?error=google_auth_denied');
}
if (!code) {
throw redirect(302, '/private/events?error=missing_auth_code');
}
// Exchange code for tokens
const oauth = getOAuthClient();
const { tokens } = await oauth.getToken(code);
if (!tokens.refresh_token || !tokens.access_token) {
throw redirect(302, '/private/events?error=incomplete_tokens');
}
// Create a success page with tokens that closes the popup and communicates with parent
const html = `
<!DOCTYPE html>
<html>
<head>
<title>Google Authentication Success</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
background: #f9fafb;
}
.container {
text-align: center;
padding: 2rem;
background: white;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.success {
color: #059669;
margin-bottom: 1rem;
}
.loading {
color: #6b7280;
}
</style>
</head>
<body>
<div class="container">
<div class="success">✓ Authentication successful!</div>
<div class="loading">Closing window...</div>
</div>
<script>
(function() {
try {
// Store tokens in the parent window's localStorage
if (window.opener && !window.opener.closed) {
window.opener.localStorage.setItem('google_access_token', '${tokens.access_token}');
window.opener.localStorage.setItem('google_refresh_token', '${tokens.refresh_token}');
// Send success message to parent
window.opener.postMessage({
type: 'GOOGLE_AUTH_SUCCESS',
tokens: {
accessToken: '${tokens.access_token}',
refreshToken: '${tokens.refresh_token}'
}
}, '*');
// Close the popup after a short delay to ensure message is received
setTimeout(() => {
window.close();
}, 500);
} else {
// If no opener, close immediately
window.close();
}
} catch (error) {
console.error('Error in auth callback:', error);
// Try to close the window anyway
setTimeout(() => {
window.close();
}, 1000);
}
})();
</script>
</body>
</html>`;
return new Response(html, {
headers: {
'Content-Type': 'text/html'
}
});
} catch (error) {
console.error('Error handling Google OAuth callback:', error);
throw redirect(302, '/private/events?error=google_auth_failed');
}
};