谷歌登录回调

This commit is contained in:
qikongjian 2025-09-21 01:12:25 +08:00
parent 795e7447b3
commit 8dd01254ea
4 changed files with 111 additions and 15 deletions

View File

@ -21,6 +21,50 @@ export async function POST(request: NextRequest) {
);
}
// 开发模式使用测试环境的OAuth处理
const isDevelopment = process.env.NODE_ENV === 'development';
const useTestEnv = isDevelopment; // 开发环境默认使用测试环境
if (useTestEnv) {
console.log('🧪 开发模式使用模拟OAuth响应');
// 解析state参数获取origin信息
let stateData: any = {};
try {
stateData = JSON.parse(state);
} catch (e) {
console.warn('无法解析state参数:', state);
}
// 模拟成功的OAuth响应
const mockResponse = {
success: true,
data: {
token: 'dev-mock-token-' + Date.now(),
user: {
userId: 'dev-user-' + Math.random().toString(36).substr(2, 9),
userName: 'Development User',
name: 'Dev User',
email: 'dev@movieflow.com',
authType: 'GOOGLE',
isNewUser: false
},
userInfo: {
userId: 'dev-user-' + Math.random().toString(36).substr(2, 9),
userName: 'Development User',
name: 'Dev User',
email: 'dev@movieflow.com',
authType: 'GOOGLE',
isNewUser: false
},
message: 'Development mode - Google authentication simulated'
}
};
console.log('返回模拟OAuth响应:', mockResponse);
return NextResponse.json(mockResponse);
}
// 解析state参数
let stateData: any = {};
try {
@ -57,7 +101,10 @@ export async function POST(request: NextRequest) {
);
}
const tokenResponse = await fetch('https://oauth2.googleapis.com/token', {
console.log('开始向Google交换token...');
// 创建fetch配置包含超时和重试机制
const fetchOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
@ -69,8 +116,32 @@ export async function POST(request: NextRequest) {
redirect_uri: getRedirectUri(request),
grant_type: 'authorization_code',
}),
});
// 增加超时时间到30秒
signal: AbortSignal.timeout(30000)
};
let tokenResponse;
try {
tokenResponse = await fetch('https://oauth2.googleapis.com/token', fetchOptions);
} catch (fetchError: any) {
console.error('Google API连接失败:', fetchError.message);
// 如果是超时错误,提供更友好的错误信息
if (fetchError.name === 'TimeoutError' || fetchError.code === 'UND_ERR_CONNECT_TIMEOUT') {
return NextResponse.json(
{
success: false,
message: 'Google authentication service is temporarily unavailable. Please check your network connection and try again.'
},
{ status: 503 }
);
}
throw fetchError;
}
console.log('Google token exchange响应状态:', tokenResponse.status);
if (!tokenResponse.ok) {
const errorText = await tokenResponse.text();
console.error('Google token exchange failed:', errorText);
@ -84,6 +155,7 @@ export async function POST(request: NextRequest) {
}
const tokenData = await tokenResponse.json();
console.log('Google token exchange成功获得token');
const { id_token } = tokenData;
if (!id_token) {
@ -99,6 +171,7 @@ export async function POST(request: NextRequest) {
// 第二步使用id_token调用Java后端
const javaBaseUrl = process.env.NEXT_PUBLIC_JAVA_URL || 'https://77.app.java.auth.qikongjian.com';
console.log('开始调用Java后端:', javaBaseUrl);
const backendResponse = await fetch(`${javaBaseUrl}/api/auth/google/login`, {
method: 'POST',
@ -113,6 +186,7 @@ export async function POST(request: NextRequest) {
})
});
console.log('Java后端响应状态:', backendResponse.status);
const backendResult = await backendResponse.json();
if (!backendResponse.ok || !backendResult.success) {
@ -144,6 +218,18 @@ export async function POST(request: NextRequest) {
} catch (error: any) {
console.error('Google OAuth回调处理错误:', error);
// 检查是否是网络连接错误
if (error.code === 'ECONNREFUSED' || error.message?.includes('fetch failed')) {
console.error('网络连接失败可能是Java后端服务不可用');
return NextResponse.json(
{
success: false,
message: 'Backend service unavailable. Please try again later.'
},
{ status: 503 }
);
}
return NextResponse.json(
{
success: false,
@ -159,9 +245,10 @@ export async function POST(request: NextRequest) {
*/
function getRedirectUri(request: NextRequest): string {
const host = request.headers.get('host') || '';
const protocol = request.headers.get('x-forwarded-proto') || 'https';
if (host.includes('localhost') || host.includes('127.0.0.1')) {
// 本地开发环境使用实际的端口号可能是3000或3001
const protocol = 'http';
return `${protocol}://${host}/api/auth/google/callback`;
} else if (host.includes('movieflow.net')) {
return 'https://www.movieflow.net/api/auth/google/callback';

View File

@ -16,6 +16,8 @@ export default function OAuthCallback() {
useEffect(() => {
const handleOAuthCallback = async () => {
try {
console.log('OAuth回调页面开始处理...');
// 获取URL参数
const params: OAuthCallbackParams = {
code: searchParams.get("code") || undefined,
@ -24,8 +26,11 @@ export default function OAuthCallback() {
error_description: searchParams.get("error_description") || undefined,
};
console.log('获取到的URL参数:', params);
// 检查是否有错误
if (params.error) {
console.error('OAuth错误:', params.error, params.error_description);
setStatus("error");
setMessage(params.error_description || `OAuth error: ${params.error}`);
return;
@ -33,6 +38,7 @@ export default function OAuthCallback() {
// 验证必需参数
if (!params.code || !params.state) {
console.error('缺少必需的OAuth参数:', { code: !!params.code, state: !!params.state });
setStatus("error");
setMessage("Missing required OAuth parameters");
return;
@ -42,8 +48,9 @@ export default function OAuthCallback() {
let stateData: any = {};
try {
stateData = JSON.parse(params.state);
console.log('解析后的State数据:', stateData);
} catch (e) {
console.warn('无法解析state参数:', params.state);
console.warn('无法解析state参数:', params.state, e);
}
console.log('开始处理Google OAuth回调, code:', params.code?.substring(0, 20) + '...');

View File

@ -18,7 +18,7 @@ export default function AuthGuard({ children }: AuthGuardProps) {
const pathname = usePathname();
// 不需要鉴权的页面
const publicPaths = ['/','/login', '/signup', '/forgot-password', '/Terms', '/Privacy', '/activate'];
const publicPaths = ['/','/login', '/signup', '/forgot-password', '/Terms', '/Privacy', '/activate', '/users/oauth/callback'];
const isPublicPath = publicPaths.includes(pathname);
useEffect(() => {

View File

@ -252,16 +252,18 @@ export const signInWithGoogle = async (inviteCode?: string): Promise<void> => {
const isProdEnv = window.location.hostname.includes('movieflow.ai');
let redirectUri;
if (isLocalhost) {
redirectUri = `${window.location.origin}/api/auth/google/callback`;
} else if (isDevEnv) {
redirectUri = 'https://www.movieflow.net/api/auth/google/callback'; // 指向正确的API端点
} else if (isProdEnv) {
redirectUri = 'https://www.movieflow.ai/api/auth/google/callback'; // 指向正确的API端点
} else {
// 默认使用生产环境
redirectUri = 'https://www.movieflow.ai/api/auth/google/callback'; // 指向正确的API端点
}
redirectUri = 'https://www.movieflow.net/api/auth/google/callback';
// if (isLocalhost) {
// // 本地开发环境:仍然使用本地地址,但后端会转发到测试环境处理
// redirectUri = `${window.location.origin}/api/auth/google/callback`;
// } else if (isDevEnv) {
// // 指向正确的API端点
// } else if (isProdEnv) {
// redirectUri = 'https://www.movieflow.ai/api/auth/google/callback'; // 指向正确的API端点
// } else {
// // 默认使用生产环境
// redirectUri = 'https://www.movieflow.ai/api/auth/google/callback'; // 指向正确的API端点
// }
console.log('使用的redirect_uri:', redirectUri);