wu981526092 commited on
Commit
5d5103b
Β·
1 Parent(s): 94b62b3

Fix: Add backend OAuth config API for client_id

Browse files

πŸ› Problem:
- HF OAuth requires client_id parameter in authorization URL
- Frontend can't directly access server environment variables
- Getting 400 'client_id is required' error

βœ… Solution:
- Created /api/auth/oauth-config endpoint in backend
- Returns public OAuth config (client_id, scopes, provider_url)
- Frontend fetches config before OAuth redirect
- Secure: Only returns public info, never client_secret

πŸ”§ Technical Changes:
Backend:
- Added get_oauth_config_for_frontend() route
- Returns OAuth config from environment variables
- Includes safety checks for auth_enabled status

Frontend:
- Fetch OAuth config from backend API before login
- Use backend-provided client_id in OAuth URL
- Enhanced error handling for config fetch failures
- Debug logging for OAuth config validation

🎯 Expected Result:
- OAuth URL now includes proper client_id parameter
- Should successfully redirect to HF OAuth page
- No more '400 client_id required' errors

backend/routers/auth.py CHANGED
@@ -49,6 +49,26 @@ async def auth_status(request: Request):
49
  }
50
 
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  @router.get("/login")
53
  async def login(request: Request):
54
  """
 
49
  }
50
 
51
 
52
+ @router.get("/oauth-config")
53
+ async def get_oauth_config_for_frontend():
54
+ """Get OAuth configuration for frontend use (public information only)."""
55
+ if not should_enable_auth():
56
+ return {"oauth_enabled": False}
57
+
58
+ config = get_oauth_config()
59
+ if not config:
60
+ return {"oauth_enabled": False, "error": "OAuth not configured"}
61
+
62
+ # Only return public information (never return client_secret)
63
+ return {
64
+ "oauth_enabled": True,
65
+ "client_id": config["client_id"],
66
+ "scopes": config["scopes"],
67
+ "provider_url": config["provider_url"],
68
+ "is_hf_spaces": is_huggingface_space()
69
+ }
70
+
71
+
72
  @router.get("/login")
73
  async def login(request: Request):
74
  """
frontend/src/context/AuthContext.tsx CHANGED
@@ -217,30 +217,48 @@ export function AuthProvider({ children }: { children: ReactNode }) {
217
  document.querySelector('meta[name="hf:space"]') !== null;
218
 
219
  if (isHFSpaces) {
220
- // In HF Spaces, use direct OAuth URL redirect
221
- // HF Spaces provides OAuth automatically when hf_oauth: true is set in README.md
222
-
223
- console.log("πŸ” Using HF Spaces direct OAuth redirect");
224
-
225
- // Direct OAuth URL construction for HF Spaces
226
- const baseUrl = window.location.origin;
227
- const redirectUri = `${baseUrl}/oauth-callback`; // Use HF standard callback
228
-
229
- // Create state for CSRF protection
230
- const state = Math.random().toString(36).substring(2, 15);
231
- localStorage.setItem("oauth_state", state);
232
-
233
- // Use HF OAuth endpoint directly - HF Spaces handles client_id automatically
234
- const oauthUrl =
235
- `https://huggingface.co/oauth/authorize?` +
236
- `response_type=code&` +
237
- `redirect_uri=${encodeURIComponent(redirectUri)}&` +
238
- `scope=openid%20profile%20read-repos&` +
239
- `state=${state}&` +
240
- `prompt=consent`;
241
-
242
- console.log("πŸ”„ Redirecting to HF OAuth:", oauthUrl);
243
- window.location.href = oauthUrl;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  } else {
245
  // For local development, show a message or redirect to HF
246
  dispatch({
 
217
  document.querySelector('meta[name="hf:space"]') !== null;
218
 
219
  if (isHFSpaces) {
220
+ // In HF Spaces, get OAuth config from backend API
221
+ console.log("πŸ” Getting OAuth config from backend");
222
+
223
+ try {
224
+ const response = await fetch('/api/auth/oauth-config');
225
+ const oauthConfig = await response.json();
226
+
227
+ if (!oauthConfig.oauth_enabled) {
228
+ throw new Error("OAuth not enabled or configured on backend");
229
+ }
230
+
231
+ console.log("βœ… OAuth config received:", {
232
+ client_id: oauthConfig.client_id?.substring(0, 8) + "...",
233
+ scopes: oauthConfig.scopes,
234
+ provider_url: oauthConfig.provider_url
235
+ });
236
+
237
+ // Direct OAuth URL construction with backend-provided client_id
238
+ const baseUrl = window.location.origin;
239
+ const redirectUri = `${baseUrl}/oauth-callback`;
240
+
241
+ // Create state for CSRF protection
242
+ const state = Math.random().toString(36).substring(2, 15);
243
+ localStorage.setItem("oauth_state", state);
244
+
245
+ // Use HF OAuth endpoint with proper client_id from backend
246
+ const oauthUrl =
247
+ `${oauthConfig.provider_url}/oauth/authorize?` +
248
+ `response_type=code&` +
249
+ `client_id=${encodeURIComponent(oauthConfig.client_id)}&` +
250
+ `redirect_uri=${encodeURIComponent(redirectUri)}&` +
251
+ `scope=${encodeURIComponent(oauthConfig.scopes)}&` +
252
+ `state=${state}&` +
253
+ `prompt=consent`;
254
+
255
+ console.log("πŸ”„ Redirecting to HF OAuth with client_id");
256
+ window.location.href = oauthUrl;
257
+
258
+ } catch (configError) {
259
+ console.error("Failed to get OAuth config from backend:", configError);
260
+ throw new Error("OAuth configuration not available from backend");
261
+ }
262
  } else {
263
  // For local development, show a message or redirect to HF
264
  dispatch({