wu981526092 commited on
Commit
0d7ac2b
·
1 Parent(s): aad2775

Fix login modal authentication issues

Browse files

🔧 Critical Fixes:
- Fix YouTube iframe permissions policy violations (removed web-share)
- Fix authentication loop after successful OAuth login
- Improve auth status endpoint to return complete user data
- Add URL parameter detection for successful authentication
- Add page focus listener to refresh auth status
- Enhanced logging for better debugging

🐛 Issues Resolved:
- Users no longer get stuck in login loop after OAuth success
- Iframe permission violations eliminated
- Auth state properly recognized after login
- Login modal correctly disappears after successful authentication

These fixes address the core authentication flow issues
identified in HF Spaces deployment.

backend/routers/auth.py CHANGED
@@ -42,8 +42,12 @@ async def auth_status(request: Request):
42
  "login_required": True, # Mandatory for OpenAI API protection
43
  "user_authenticated": bool(user),
44
  "user_info": {
45
- "auth_method": user.get("auth_method") if user else None,
46
  "username": user.get("username") if user else None,
 
 
 
 
47
  } if user else None,
48
  "hf_sign_detected": bool(request.query_params.get("__sign")) if is_huggingface_space() else False,
49
  }
@@ -245,8 +249,8 @@ async def oauth_callback(request: Request, code: str, state: str):
245
 
246
  logger.info(f"User logged in: {user_info.get('name')} ({user_info.get('login')})")
247
 
248
- # Redirect to main application
249
- return RedirectResponse(url="/", status_code=302)
250
 
251
 
252
  @router.get("/logout")
 
42
  "login_required": True, # Mandatory for OpenAI API protection
43
  "user_authenticated": bool(user),
44
  "user_info": {
45
+ "id": user.get("id") if user else None,
46
  "username": user.get("username") if user else None,
47
+ "name": user.get("name") if user else None,
48
+ "email": user.get("email") if user else None,
49
+ "avatar_url": user.get("avatar_url") if user else None,
50
+ "auth_method": user.get("auth_method") if user else None,
51
  } if user else None,
52
  "hf_sign_detected": bool(request.query_params.get("__sign")) if is_huggingface_space() else False,
53
  }
 
249
 
250
  logger.info(f"User logged in: {user_info.get('name')} ({user_info.get('login')})")
251
 
252
+ # Redirect to main application with auth success indicator
253
+ return RedirectResponse(url="/?auth=success", status_code=302)
254
 
255
 
256
  @router.get("/logout")
frontend/src/components/auth/LoginModal.tsx CHANGED
@@ -95,7 +95,7 @@ export function LoginModal({ isOpen, onClose }: LoginModalProps) {
95
  <iframe
96
  src="https://www.youtube.com/embed/btrS9pfDYJY?si=dDX4tIs-oS2O2d2p"
97
  title="AgentGraph: Interactive Analysis Platform Demo"
98
- allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
99
  allowFullScreen
100
  className="w-full h-full rounded-xl"
101
  />
 
95
  <iframe
96
  src="https://www.youtube.com/embed/btrS9pfDYJY?si=dDX4tIs-oS2O2d2p"
97
  title="AgentGraph: Interactive Analysis Platform Demo"
98
+ allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
99
  allowFullScreen
100
  className="w-full h-full rounded-xl"
101
  />
frontend/src/context/AuthContext.tsx CHANGED
@@ -67,7 +67,7 @@ export function AuthProvider({ children }: AuthProviderProps) {
67
 
68
  if (data.user_authenticated && data.user_info) {
69
  setUser({
70
- id: data.user_info.user_id || "unknown",
71
  username: data.user_info.username || "Unknown User",
72
  name:
73
  data.user_info.name || data.user_info.username || "Unknown User",
@@ -76,8 +76,13 @@ export function AuthProvider({ children }: AuthProviderProps) {
76
  auth_method: data.user_info.auth_method || "unknown",
77
  });
78
  setShowLoginModal(false);
 
 
 
 
79
  } else {
80
  setUser(null);
 
81
  // Show login modal if in HF Spaces and auth is required
82
  if (data.environment === "huggingface_spaces" && data.login_required) {
83
  setShowLoginModal(true);
@@ -125,7 +130,17 @@ export function AuthProvider({ children }: AuthProviderProps) {
125
  };
126
 
127
  useEffect(() => {
128
- checkAuthStatus();
 
 
 
 
 
 
 
 
 
 
129
 
130
  // Listen for auth-required events from API calls
131
  const handleAuthRequired = () => {
@@ -134,12 +149,20 @@ export function AuthProvider({ children }: AuthProviderProps) {
134
  }
135
  };
136
 
137
- window.addEventListener('auth-required', handleAuthRequired);
138
-
 
 
 
 
 
 
 
139
  return () => {
140
- window.removeEventListener('auth-required', handleAuthRequired);
 
141
  };
142
- }, [authRequired, isAuthenticated]);
143
 
144
  const value: AuthContextType = {
145
  user,
 
67
 
68
  if (data.user_authenticated && data.user_info) {
69
  setUser({
70
+ id: data.user_info.id || "unknown",
71
  username: data.user_info.username || "Unknown User",
72
  name:
73
  data.user_info.name || data.user_info.username || "Unknown User",
 
76
  auth_method: data.user_info.auth_method || "unknown",
77
  });
78
  setShowLoginModal(false);
79
+ console.log(
80
+ "✅ User authenticated successfully:",
81
+ data.user_info.username
82
+ );
83
  } else {
84
  setUser(null);
85
+ console.log("❌ User not authenticated - showing login modal");
86
  // Show login modal if in HF Spaces and auth is required
87
  if (data.environment === "huggingface_spaces" && data.login_required) {
88
  setShowLoginModal(true);
 
130
  };
131
 
132
  useEffect(() => {
133
+ // Check for auth success parameter in URL
134
+ const urlParams = new URLSearchParams(window.location.search);
135
+ if (urlParams.get('auth') === 'success') {
136
+ console.log("Authentication success detected - refreshing status");
137
+ // Remove the parameter from URL
138
+ window.history.replaceState({}, document.title, window.location.pathname);
139
+ // Force auth status check
140
+ setTimeout(() => checkAuthStatus(), 100);
141
+ } else {
142
+ checkAuthStatus();
143
+ }
144
 
145
  // Listen for auth-required events from API calls
146
  const handleAuthRequired = () => {
 
149
  }
150
  };
151
 
152
+ // Listen for page focus to refresh auth status (useful after OAuth redirect)
153
+ const handleFocus = () => {
154
+ console.log("Page focused - checking auth status");
155
+ checkAuthStatus();
156
+ };
157
+
158
+ window.addEventListener("auth-required", handleAuthRequired);
159
+ window.addEventListener("focus", handleFocus);
160
+
161
  return () => {
162
+ window.removeEventListener("auth-required", handleAuthRequired);
163
+ window.removeEventListener("focus", handleFocus);
164
  };
165
+ }, []);
166
 
167
  const value: AuthContextType = {
168
  user,
frontend/src/lib/api.ts CHANGED
@@ -36,13 +36,17 @@ async function fetchApi<T>(
36
  // Handle 401 (Unauthorized) - trigger login modal
37
  if (response.status === 401) {
38
  // Check if running in browser environment
39
- if (typeof window !== 'undefined') {
40
  // Dispatch a custom event to trigger login modal
41
- window.dispatchEvent(new CustomEvent('auth-required', {
42
- detail: { message: 'Authentication required to access this feature' }
43
- }));
 
 
 
 
44
  }
45
- throw new ApiError(response.status, 'Authentication required');
46
  }
47
 
48
  // Handle 429 (Too Many Requests) with exponential backoff
 
36
  // Handle 401 (Unauthorized) - trigger login modal
37
  if (response.status === 401) {
38
  // Check if running in browser environment
39
+ if (typeof window !== "undefined") {
40
  // Dispatch a custom event to trigger login modal
41
+ window.dispatchEvent(
42
+ new CustomEvent("auth-required", {
43
+ detail: {
44
+ message: "Authentication required to access this feature",
45
+ },
46
+ })
47
+ );
48
  }
49
+ throw new ApiError(response.status, "Authentication required");
50
  }
51
 
52
  // Handle 429 (Too Many Requests) with exponential backoff