forked from 77media/video-flow
谷歌登录回调
This commit is contained in:
parent
795e7447b3
commit
8dd01254ea
@ -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参数
|
// 解析state参数
|
||||||
let stateData: any = {};
|
let stateData: any = {};
|
||||||
try {
|
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',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
@ -69,8 +116,32 @@ export async function POST(request: NextRequest) {
|
|||||||
redirect_uri: getRedirectUri(request),
|
redirect_uri: getRedirectUri(request),
|
||||||
grant_type: 'authorization_code',
|
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) {
|
if (!tokenResponse.ok) {
|
||||||
const errorText = await tokenResponse.text();
|
const errorText = await tokenResponse.text();
|
||||||
console.error('Google token exchange failed:', errorText);
|
console.error('Google token exchange failed:', errorText);
|
||||||
@ -84,6 +155,7 @@ export async function POST(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const tokenData = await tokenResponse.json();
|
const tokenData = await tokenResponse.json();
|
||||||
|
console.log('Google token exchange成功,获得token');
|
||||||
const { id_token } = tokenData;
|
const { id_token } = tokenData;
|
||||||
|
|
||||||
if (!id_token) {
|
if (!id_token) {
|
||||||
@ -99,6 +171,7 @@ export async function POST(request: NextRequest) {
|
|||||||
|
|
||||||
// 第二步:使用id_token调用Java后端
|
// 第二步:使用id_token调用Java后端
|
||||||
const javaBaseUrl = process.env.NEXT_PUBLIC_JAVA_URL || 'https://77.app.java.auth.qikongjian.com';
|
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`, {
|
const backendResponse = await fetch(`${javaBaseUrl}/api/auth/google/login`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -113,6 +186,7 @@ export async function POST(request: NextRequest) {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('Java后端响应状态:', backendResponse.status);
|
||||||
const backendResult = await backendResponse.json();
|
const backendResult = await backendResponse.json();
|
||||||
|
|
||||||
if (!backendResponse.ok || !backendResult.success) {
|
if (!backendResponse.ok || !backendResult.success) {
|
||||||
@ -144,6 +218,18 @@ export async function POST(request: NextRequest) {
|
|||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Google OAuth回调处理错误:', error);
|
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(
|
return NextResponse.json(
|
||||||
{
|
{
|
||||||
success: false,
|
success: false,
|
||||||
@ -159,9 +245,10 @@ export async function POST(request: NextRequest) {
|
|||||||
*/
|
*/
|
||||||
function getRedirectUri(request: NextRequest): string {
|
function getRedirectUri(request: NextRequest): string {
|
||||||
const host = request.headers.get('host') || '';
|
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')) {
|
if (host.includes('localhost') || host.includes('127.0.0.1')) {
|
||||||
|
// 本地开发环境:使用实际的端口号(可能是3000或3001)
|
||||||
|
const protocol = 'http';
|
||||||
return `${protocol}://${host}/api/auth/google/callback`;
|
return `${protocol}://${host}/api/auth/google/callback`;
|
||||||
} else if (host.includes('movieflow.net')) {
|
} else if (host.includes('movieflow.net')) {
|
||||||
return 'https://www.movieflow.net/api/auth/google/callback';
|
return 'https://www.movieflow.net/api/auth/google/callback';
|
||||||
|
|||||||
@ -16,6 +16,8 @@ export default function OAuthCallback() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleOAuthCallback = async () => {
|
const handleOAuthCallback = async () => {
|
||||||
try {
|
try {
|
||||||
|
console.log('OAuth回调页面开始处理...');
|
||||||
|
|
||||||
// 获取URL参数
|
// 获取URL参数
|
||||||
const params: OAuthCallbackParams = {
|
const params: OAuthCallbackParams = {
|
||||||
code: searchParams.get("code") || undefined,
|
code: searchParams.get("code") || undefined,
|
||||||
@ -24,8 +26,11 @@ export default function OAuthCallback() {
|
|||||||
error_description: searchParams.get("error_description") || undefined,
|
error_description: searchParams.get("error_description") || undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log('获取到的URL参数:', params);
|
||||||
|
|
||||||
// 检查是否有错误
|
// 检查是否有错误
|
||||||
if (params.error) {
|
if (params.error) {
|
||||||
|
console.error('OAuth错误:', params.error, params.error_description);
|
||||||
setStatus("error");
|
setStatus("error");
|
||||||
setMessage(params.error_description || `OAuth error: ${params.error}`);
|
setMessage(params.error_description || `OAuth error: ${params.error}`);
|
||||||
return;
|
return;
|
||||||
@ -33,6 +38,7 @@ export default function OAuthCallback() {
|
|||||||
|
|
||||||
// 验证必需参数
|
// 验证必需参数
|
||||||
if (!params.code || !params.state) {
|
if (!params.code || !params.state) {
|
||||||
|
console.error('缺少必需的OAuth参数:', { code: !!params.code, state: !!params.state });
|
||||||
setStatus("error");
|
setStatus("error");
|
||||||
setMessage("Missing required OAuth parameters");
|
setMessage("Missing required OAuth parameters");
|
||||||
return;
|
return;
|
||||||
@ -42,8 +48,9 @@ export default function OAuthCallback() {
|
|||||||
let stateData: any = {};
|
let stateData: any = {};
|
||||||
try {
|
try {
|
||||||
stateData = JSON.parse(params.state);
|
stateData = JSON.parse(params.state);
|
||||||
|
console.log('解析后的State数据:', stateData);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn('无法解析state参数:', params.state);
|
console.warn('无法解析state参数:', params.state, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('开始处理Google OAuth回调, code:', params.code?.substring(0, 20) + '...');
|
console.log('开始处理Google OAuth回调, code:', params.code?.substring(0, 20) + '...');
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export default function AuthGuard({ children }: AuthGuardProps) {
|
|||||||
const pathname = usePathname();
|
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);
|
const isPublicPath = publicPaths.includes(pathname);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
22
lib/auth.ts
22
lib/auth.ts
@ -252,16 +252,18 @@ export const signInWithGoogle = async (inviteCode?: string): Promise<void> => {
|
|||||||
const isProdEnv = window.location.hostname.includes('movieflow.ai');
|
const isProdEnv = window.location.hostname.includes('movieflow.ai');
|
||||||
|
|
||||||
let redirectUri;
|
let redirectUri;
|
||||||
if (isLocalhost) {
|
redirectUri = 'https://www.movieflow.net/api/auth/google/callback';
|
||||||
redirectUri = `${window.location.origin}/api/auth/google/callback`;
|
// if (isLocalhost) {
|
||||||
} else if (isDevEnv) {
|
// // 本地开发环境:仍然使用本地地址,但后端会转发到测试环境处理
|
||||||
redirectUri = 'https://www.movieflow.net/api/auth/google/callback'; // 指向正确的API端点
|
// redirectUri = `${window.location.origin}/api/auth/google/callback`;
|
||||||
} else if (isProdEnv) {
|
// } else if (isDevEnv) {
|
||||||
redirectUri = 'https://www.movieflow.ai/api/auth/google/callback'; // 指向正确的API端点
|
// // 指向正确的API端点
|
||||||
} else {
|
// } else if (isProdEnv) {
|
||||||
// 默认使用生产环境
|
// redirectUri = 'https://www.movieflow.ai/api/auth/google/callback'; // 指向正确的API端点
|
||||||
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);
|
console.log('使用的redirect_uri:', redirectUri);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user