处理回调

This commit is contained in:
Xin Wang 2025-06-30 20:33:53 +08:00
parent c3c3253723
commit 6371c9d05f
4 changed files with 47 additions and 3 deletions

View File

@ -18,10 +18,17 @@ export async function GET(request: NextRequest) {
const error = searchParams.get('error'); const error = searchParams.get('error');
const state = searchParams.get('state'); const state = searchParams.get('state');
console.log('Google OAuth callback received', {
hasCode: !!code,
error: error || 'none',
hasState: !!state,
url: request.url
});
// Handle errors from Google // Handle errors from Google
if (error) { if (error) {
console.error('Google OAuth error:', error); console.error('Google OAuth error:', error);
return NextResponse.redirect(new URL('/login?error=google_oauth', request.url)); return NextResponse.redirect(new URL(`/login?error=${encodeURIComponent(error)}`, request.url));
} }
if (!code) { if (!code) {
@ -34,6 +41,8 @@ export async function GET(request: NextRequest) {
// We'll add the state to the redirect URL so the client can validate it // We'll add the state to the redirect URL so the client can validate it
try { try {
console.log('Processing OAuth callback with code', code.substring(0, 5) + '...');
// In a real app, you would exchange the code for tokens // In a real app, you would exchange the code for tokens
// and validate the tokens here // and validate the tokens here
@ -61,9 +70,11 @@ export async function GET(request: NextRequest) {
redirectUrl.searchParams.set('state', state); redirectUrl.searchParams.set('state', state);
} }
console.log('Redirecting to:', redirectUrl.toString());
return NextResponse.redirect(redirectUrl); return NextResponse.redirect(redirectUrl);
} catch (error) { } catch (error) {
console.error('Failed to process Google authentication:', error); console.error('Failed to process Google authentication:', error);
return NextResponse.redirect(new URL('/login?error=auth_failed', request.url)); const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return NextResponse.redirect(new URL(`/login?error=auth_failed&details=${encodeURIComponent(errorMessage)}`, request.url));
} }
} }

View File

@ -3,9 +3,16 @@ import type { Metadata } from 'next';
import { Inter } from 'next/font/google'; import { Inter } from 'next/font/google';
import { ThemeProvider } from '@/components/theme-provider'; import { ThemeProvider } from '@/components/theme-provider';
import { Toaster } from '@/components/ui/sonner'; import { Toaster } from '@/components/ui/sonner';
import dynamic from 'next/dynamic';
const inter = Inter({ subsets: ['latin'] }); const inter = Inter({ subsets: ['latin'] });
// Import the OAuthCallbackHandler dynamically to ensure it only runs on the client
const OAuthCallbackHandler = dynamic(
() => import('@/components/ui/oauth-callback-handler').then(mod => mod.OAuthCallbackHandler),
{ ssr: false }
);
export const metadata: Metadata = { export const metadata: Metadata = {
title: 'AI Movie Flow - Create Amazing Videos with AI', title: 'AI Movie Flow - Create Amazing Videos with AI',
description: 'Professional AI-powered video creation platform with advanced editing tools', description: 'Professional AI-powered video creation platform with advanced editing tools',
@ -27,6 +34,7 @@ export default function RootLayout({
> >
{children} {children}
<Toaster /> <Toaster />
<OAuthCallbackHandler />
</ThemeProvider> </ThemeProvider>
</body> </body>
</html> </html>

View File

@ -14,6 +14,27 @@ export function OAuthCallbackHandler() {
const state = searchParams.get('state'); const state = searchParams.get('state');
const session = searchParams.get('session'); const session = searchParams.get('session');
const userJson = searchParams.get('user'); const userJson = searchParams.get('user');
const error = searchParams.get('error');
// Log debug information
console.log('OAuth callback handler running with params:', {
state: state || 'not present',
session: session ? 'present' : 'not present',
userJson: userJson ? 'present' : 'not present',
error: error || 'none'
});
// Handle error case
if (error) {
console.error('OAuth error:', error);
toast({
title: 'Authentication Error',
description: `Google sign-in failed: ${error}`,
variant: 'destructive',
});
router.push(`/login?error=${error}`);
return;
}
// If we have state and session, this might be an OAuth callback // If we have state and session, this might be an OAuth callback
if (state && session) { if (state && session) {
@ -22,6 +43,7 @@ export function OAuthCallbackHandler() {
if (!isValid) { if (!isValid) {
// State validation failed, possible CSRF attack // State validation failed, possible CSRF attack
console.error('OAuth state validation failed');
toast({ toast({
title: 'Authentication Error', title: 'Authentication Error',
description: 'Security validation failed. Please try signing in again.', description: 'Security validation failed. Please try signing in again.',
@ -31,10 +53,13 @@ export function OAuthCallbackHandler() {
return; return;
} }
console.log('OAuth state validation successful');
// State is valid, process the login // State is valid, process the login
if (userJson) { if (userJson) {
try { try {
const user = JSON.parse(decodeURIComponent(userJson)); const user = JSON.parse(decodeURIComponent(userJson));
console.log('OAuth user data parsed successfully');
// Store the user in session // Store the user in session
sessionStorage.setItem('currentUser', JSON.stringify(user)); sessionStorage.setItem('currentUser', JSON.stringify(user));

View File

@ -1,7 +1,7 @@
// Mock Google OAuth configuration // Mock Google OAuth configuration
const GOOGLE_CLIENT_ID = '1016208801816-qtvcvki2jobmcin1g4e7u4sotr0p8g3u.apps.googleusercontent.com'; const GOOGLE_CLIENT_ID = '1016208801816-qtvcvki2jobmcin1g4e7u4sotr0p8g3u.apps.googleusercontent.com';
const GOOGLE_REDIRECT_URI = typeof window !== 'undefined' const GOOGLE_REDIRECT_URI = typeof window !== 'undefined'
? `${window.location.origin}/api/auth/google/callback` ? 'https://movieflow.api.huiying.video/oauth/callback'
: ''; : '';
/** /**