Skip to content

Commit b19bebc

Browse files
committed
fix: enhance authentication flow and improve error handling in middleware and components
- Added detailed logging in the middleware to track access token validation and redirect logic. - Improved error handling in the Google login callback by utilizing the auth hook for token management. - Removed the deprecated set-token API route to streamline authentication processes. - Enhanced cookie management and debugging information in the customers page for better user experience during authentication checks.
1 parent d1b77aa commit b19bebc

File tree

6 files changed

+149
-96
lines changed

6 files changed

+149
-96
lines changed

backend/app/core/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ def _check_default_secret(self, var_name: str, value: str | None) -> None:
211211
"""Check if the provided secret value is "nexus" and raise a warning or error."""
212212
if value == "nexus":
213213
message = (
214+
214215
f'The value of {var_name} is "nexus", '
215216
"for security, please change it, at least for deployments."
216217
)

frontend/app/api/auth/set-token/route.ts

Lines changed: 0 additions & 32 deletions
This file was deleted.

frontend/app/customers/page.tsx

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,29 +23,66 @@ export default function CustomersPage() {
2323
const checkAuth = async () => {
2424
try {
2525
const apiUrl = process.env.NEXT_PUBLIC_API_URL || "http://127.0.0.1:8000";
26+
27+
// 更详细地检查cookie
28+
console.log("[Customer] 检查cookie信息");
29+
console.log("[Customer] 全部cookie:", document.cookie);
30+
2631
const token = document.cookie
2732
.split('; ')
2833
.find(row => row.startsWith('accessToken='))
2934
?.split('=')[1];
3035

36+
console.log("[Customer] accessToken:", token ? `${token.substring(0, 10)}...` : "Missing");
37+
3138
if (token) {
39+
console.log("[Customer] 尝试获取用户信息");
3240
const response = await fetch(`${apiUrl}/api/v1/users/me`, {
3341
headers: {
3442
Authorization: `Bearer ${token}`,
3543
},
44+
credentials: 'include', // 包含cookies
3645
});
3746

47+
const status = response.status;
48+
console.log("[Customer] API响应状态:", status);
49+
50+
if (!response.ok) {
51+
const errorText = await response.text();
52+
console.error("[Customer] API错误:", errorText);
53+
setDebugInfo({
54+
status,
55+
error: errorText,
56+
token: token ? '部分显示: ' + token.substring(0, 10) + '...' : 'Missing',
57+
fullCookies: document.cookie,
58+
});
59+
return;
60+
}
61+
3862
const data = await response.json();
63+
console.log("[Customer] 获取到的用户数据:", data);
64+
3965
setDebugInfo({
40-
status: response.status,
41-
data: data,
42-
token: token ? 'Present' : 'Missing',
66+
status,
67+
data,
68+
token: token ? '部分显示: ' + token.substring(0, 10) + '...' : 'Missing',
69+
fullCookies: document.cookie,
4370
});
4471
} else {
45-
setDebugInfo({ token: 'Missing' });
72+
console.log("[Customer] 未找到token");
73+
setDebugInfo({
74+
token: 'Missing',
75+
fullCookies: document.cookie,
76+
timestamp: new Date().toISOString(),
77+
});
4678
}
4779
} catch (e) {
48-
setDebugInfo({ error: e instanceof Error ? e.message : String(e) });
80+
console.error("[Customer] 检查认证时出错:", e);
81+
setDebugInfo({
82+
error: e instanceof Error ? e.message : String(e),
83+
fullCookies: document.cookie,
84+
timestamp: new Date().toISOString(),
85+
});
4986
}
5087
};
5188

frontend/app/login/google/callback/page.tsx

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
import { useEffect, Suspense } from "react";
44
import { useRouter, useSearchParams } from "next/navigation";
5+
import { useAuth } from "@/lib/auth";
56

67
// 创建一个内部组件处理参数
78
function CallbackContent() {
89
const searchParams = useSearchParams();
910
const router = useRouter();
11+
const { login } = useAuth();
1012

1113
useEffect(() => {
1214
// 从URL获取token参数
@@ -28,32 +30,21 @@ function CallbackContent() {
2830
return;
2931
}
3032

31-
// 客户端处理token和Cookie
32-
const handleToken = async () => {
33-
try {
34-
// 使用fetch API设置cookie
35-
const response = await fetch('/api/auth/set-token', {
36-
method: 'POST',
37-
headers: {
38-
'Content-Type': 'application/json',
39-
},
40-
body: JSON.stringify({ token }),
41-
});
42-
43-
if (!response.ok) {
44-
throw new Error('Failed to set authentication token');
45-
}
46-
47-
// 成功后导航到dashboard
33+
// 使用auth hook的login方法设置cookie
34+
try {
35+
console.log("Setting token from Google login");
36+
login(token);
37+
38+
// 添加延迟以确保token被设置和处理
39+
setTimeout(() => {
40+
console.log("Navigating to dashboard after Google login");
4841
router.push('/dashboard');
49-
} catch (error) {
50-
console.error("Error setting token:", error);
51-
router.push("/login?error=token_processing_error");
52-
}
53-
};
54-
55-
handleToken();
56-
}, [searchParams, router]);
42+
}, 500);
43+
} catch (error) {
44+
console.error("Error processing Google login token:", error);
45+
router.push("/login?error=token_processing_error");
46+
}
47+
}, [searchParams, router, login]);
5748

5849
return (
5950
<div className="flex min-h-screen flex-col items-center justify-center">

frontend/lib/auth.ts

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,11 @@ export function useAuth(): AuthContextType {
3535
setError(null);
3636

3737
const token = getCookie("accessToken");
38+
39+
console.log("[Auth] 尝试获取accessToken:", token ? "存在" : "不存在");
40+
3841
if (!token) {
39-
console.log("No access token found");
42+
console.log("[Auth] No access token found");
4043
setIsLoading(false);
4144
return;
4245
}
@@ -49,32 +52,33 @@ export function useAuth(): AuthContextType {
4952
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
5053
}).join(''));
5154

52-
console.log("JWT Payload:", JSON.parse(jsonPayload));
55+
console.log("[Auth] JWT Payload:", JSON.parse(jsonPayload));
5356
} catch (e) {
54-
console.error("Failed to decode JWT:", e);
57+
console.error("[Auth] Failed to decode JWT:", e);
5558
}
5659

5760
// In a real implementation, you would fetch from your API
5861
const apiUrl = process.env.NEXT_PUBLIC_API_URL || "http://127.0.0.1:8000";
59-
console.log(`Fetching user data from ${apiUrl}/api/v1/users/me`);
62+
console.log(`[Auth] Fetching user data from ${apiUrl}/api/v1/users/me`);
6063

6164
const response = await fetch(`${apiUrl}/api/v1/users/me`, {
6265
headers: {
6366
Authorization: `Bearer ${token}`,
6467
},
68+
credentials: 'include', // 包含cookies
6569
});
6670

6771
if (!response.ok) {
6872
const errorText = await response.text();
69-
console.error("API Error:", response.status, errorText);
73+
console.error("[Auth] API Error:", response.status, errorText);
7074
throw new Error(`Failed to fetch user data: ${response.status} ${errorText}`);
7175
}
7276

7377
const userData = await response.json();
74-
console.log("User data fetched successfully:", userData);
78+
console.log("[Auth] User data fetched successfully:", userData);
7579
setUser(userData);
7680
} catch (err) {
77-
console.error("Error in fetchUser:", err);
81+
console.error("[Auth] Error in fetchUser:", err);
7882
setError(
7983
err instanceof Error ? err : new Error("An unknown error occurred"),
8084
);
@@ -98,6 +102,7 @@ export function useAuth(): AuthContextType {
98102
"Content-Type": "application/json",
99103
},
100104
body: JSON.stringify(userData),
105+
credentials: 'include', // 包含cookies
101106
});
102107

103108
if (!response.ok) {
@@ -108,7 +113,7 @@ export function useAuth(): AuthContextType {
108113
const updatedUser = await response.json();
109114
setUser(updatedUser);
110115
} catch (err) {
111-
console.error("Error in updateUser:", err);
116+
console.error("[Auth] Error in updateUser:", err);
112117
setError(
113118
err instanceof Error ? err : new Error("An unknown error occurred"),
114119
);
@@ -117,31 +122,51 @@ export function useAuth(): AuthContextType {
117122
};
118123

119124
const login = (token: string) => {
120-
// Store the token in a cookie
121-
document.cookie = `accessToken=${token};path=/;max-age=${60 * 60 * 24 * 7}`; // 7 days
122-
console.log("Access token stored in cookie");
123-
// Fetch user data after login
124-
fetchUser();
125+
try {
126+
console.log("[Auth] Setting access token in cookie");
127+
128+
// 确保token有效
129+
if (!token || token.trim() === '') {
130+
console.error("[Auth] Invalid token provided");
131+
return;
132+
}
133+
134+
// 设置cookie,添加更多安全选项
135+
const cookieValue = `accessToken=${token};path=/;max-age=${60 * 60 * 24 * 7}`;
136+
document.cookie = cookieValue;
137+
138+
// 验证cookie是否设置成功
139+
const savedToken = getCookie("accessToken");
140+
console.log("[Auth] Token saved in cookie:", savedToken ? "成功" : "失败");
141+
142+
// 打印所有的cookie以便调试
143+
console.log("[Auth] Current cookies:", document.cookie);
144+
145+
// Fetch user data after login
146+
fetchUser();
147+
} catch (error) {
148+
console.error("[Auth] Error setting token in cookie:", error);
149+
}
125150
};
126151

127152
const logout = () => {
128153
// Clear the token
129154
document.cookie = "accessToken=;path=/;max-age=0";
130-
console.log("Access token cleared");
155+
console.log("[Auth] Access token cleared");
131156
// Reset user
132157
setUser(null);
133158
// Redirect to login page
134159
router.push("/login");
135160
};
136161

137162
useEffect(() => {
138-
console.log("Auth hook mounted, checking for token");
163+
console.log("[Auth] Auth hook mounted, checking for token");
139164
const token = getCookie("accessToken");
140165
if (token) {
141-
console.log("Token found, fetching user");
166+
console.log("[Auth] Token found, fetching user");
142167
fetchUser();
143168
} else {
144-
console.log("No token found");
169+
console.log("[Auth] No token found");
145170
setIsLoading(false);
146171
}
147172
}, []);
@@ -158,12 +183,24 @@ export function useAuth(): AuthContextType {
158183

159184
// Helper to get cookie value on client side
160185
function getCookie(name: string): string | undefined {
161-
if (typeof document === "undefined") return undefined;
186+
if (typeof document === "undefined") {
187+
console.log("[Auth] getCookie: document is undefined (server side)");
188+
return undefined;
189+
}
162190

163-
const value = `; ${document.cookie}`;
164-
const parts = value.split(`; ${name}=`);
165-
if (parts.length === 2) {
166-
return parts.pop()?.split(";").shift();
191+
console.log("[Auth] getCookie: 搜索cookie:", name);
192+
console.log("[Auth] getCookie: 所有cookie:", document.cookie);
193+
194+
const cookies = document.cookie.split(';');
195+
for (let i = 0; i < cookies.length; i++) {
196+
const cookie = cookies[i].trim();
197+
if (cookie.startsWith(name + '=')) {
198+
const value = cookie.substring(name.length + 1);
199+
console.log(`[Auth] getCookie: 找到 ${name} = ${value.substring(0, 10)}...`);
200+
return value;
201+
}
167202
}
203+
204+
console.log(`[Auth] getCookie: ${name} 未找到`);
168205
return undefined;
169206
}

frontend/middleware.ts

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,43 @@ import type { NextRequest } from "next/server";
33
import { readUserMe } from "@/app/clientService";
44

55
export async function middleware(request: NextRequest) {
6+
console.log("[Middleware] 处理路径:", request.nextUrl.pathname);
7+
8+
// 检查cookies
69
const token = request.cookies.get("accessToken");
7-
10+
console.log("[Middleware] accessToken:", token ? "存在" : "不存在");
11+
812
if (!token) {
9-
return NextResponse.redirect(new URL("/login", request.url));
13+
console.log("[Middleware] 没有token,重定向到登录页面");
14+
// 保存原始URL以便登录后重定向回来
15+
const redirectUrl = new URL("/login", request.url);
16+
redirectUrl.searchParams.set("callbackUrl", request.nextUrl.pathname);
17+
return NextResponse.redirect(redirectUrl);
1018
}
1119

12-
const options = {
13-
headers: {
14-
Authorization: `Bearer ${token.value}`,
15-
},
16-
};
17-
18-
const { error } = await readUserMe(options);
19-
20-
if (error) {
20+
try {
21+
const options = {
22+
headers: {
23+
Authorization: `Bearer ${token.value}`,
24+
},
25+
};
26+
27+
console.log("[Middleware] 验证token有效性");
28+
const { data, error } = await readUserMe(options);
29+
30+
if (error) {
31+
console.log("[Middleware] 验证失败:", error);
32+
return NextResponse.redirect(new URL("/login", request.url));
33+
}
34+
35+
console.log("[Middleware] 验证成功, 用户:", data?.email);
36+
const response = NextResponse.next();
37+
return response;
38+
39+
} catch (e) {
40+
console.error("[Middleware] 处理请求时出错:", e);
2141
return NextResponse.redirect(new URL("/login", request.url));
2242
}
23-
return NextResponse.next();
2443
}
2544

2645
export const config = {

0 commit comments

Comments
 (0)