diff --git a/frontend/src/api/services/authService.ts b/frontend/src/api/services/authService.ts index 6b059784..e252a89f 100644 --- a/frontend/src/api/services/authService.ts +++ b/frontend/src/api/services/authService.ts @@ -52,7 +52,7 @@ export class AuthService { */ async register(userData: RegisterRequest): Promise { const response = await apiClient.post>( - '/auth/register', + '/api/v1/auth/register', userData ); diff --git a/frontend/src/contexts/AuthContext.tsx b/frontend/src/contexts/AuthContext.tsx index 61d4636f..900ffd97 100644 --- a/frontend/src/contexts/AuthContext.tsx +++ b/frontend/src/contexts/AuthContext.tsx @@ -1,19 +1,19 @@ // frontend/src/contexts/AuthContext.tsx - FIXED VERSION import React, { createContext, useContext, useEffect, useState, useCallback } from 'react'; +// FIXED: Import authService directly, not through the index import { authService } from '../api/services/authService'; import { tokenManager } from '../api/auth/tokenManager'; import { UserProfile, RegisterRequest, - api -} from '../api/services'; +} from '../api/types/api'; interface AuthContextType { user: UserProfile | null; isAuthenticated: boolean; isLoading: boolean; login: (email: string, password: string) => Promise; - register: (data: RegisterRequest) => Promise; // FIXED: Use RegisterRequest + register: (data: RegisterRequest) => Promise; logout: () => Promise; updateProfile: (updates: Partial) => Promise; refreshUser: () => Promise; @@ -39,7 +39,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children try { await tokenManager.initialize(); - if (api.auth.isAuthenticated()) { + if (authService.isAuthenticated()) { // Get user from token first (faster), then validate with API const tokenUser = tokenManager.getUserFromToken(); if (tokenUser) { @@ -58,7 +58,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children // Validate with API and get complete profile try { - const profile = await api.auth.getCurrentUser(); + const profile = await authService.getCurrentUser(); setUser(profile); } catch (error) { console.error('Failed to fetch user profile:', error); @@ -84,7 +84,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children const tokenResponse = await authService.login({ email, password }); // After login, get user profile - const profile = await api.auth.getCurrentUser(); + const profile = await authService.getCurrentUser(); setUser(profile); } catch (error) { setIsLoading(false); @@ -101,7 +101,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children const tokenResponse = await authService.register(data); // After registration, get user profile - const profile = await api.auth.getCurrentUser(); + const profile = await authService.getCurrentUser(); setUser(profile); } catch (error) { setIsLoading(false); @@ -139,10 +139,10 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }, [user]); const refreshUser = useCallback(async () => { - if (!api.auth.isAuthenticated()) return; + if (!authService.isAuthenticated()) return; try { - const profile = await api.auth.getCurrentUser(); + const profile = await authService.getCurrentUser(); setUser(profile); } catch (error) { console.error('User refresh error:', error); @@ -175,7 +175,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children if (!user) return; const checkTokenValidity = () => { - if (!api.auth.isAuthenticated()) { + if (!authService.isAuthenticated()) { console.warn('Token became invalid, logging out user'); logout(); } @@ -188,7 +188,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children const contextValue = { user, - isAuthenticated: !!user && api.auth.isAuthenticated(), + isAuthenticated: !!user && authService.isAuthenticated(), isLoading, login, register, diff --git a/gateway/app/middleware/auth.py b/gateway/app/middleware/auth.py index 63c8d141..2d13035d 100644 --- a/gateway/app/middleware/auth.py +++ b/gateway/app/middleware/auth.py @@ -54,6 +54,10 @@ class AuthMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next) -> Response: """Process request with enhanced authentication""" + # Skip authentication for OPTIONS requests (CORS preflight) + if request.method == "OPTIONS": + return await call_next(request) + # Skip authentication for public routes if self._is_public_route(request.url.path): return await call_next(request) diff --git a/gateway/app/routes/auth.py b/gateway/app/routes/auth.py index cf33249f..2ea27026 100644 --- a/gateway/app/routes/auth.py +++ b/gateway/app/routes/auth.py @@ -44,6 +44,19 @@ class AuthProxy: ) -> Response: """Forward request to auth service with proper error handling""" + # Handle OPTIONS requests directly for CORS + if request.method == "OPTIONS": + return Response( + status_code=200, + headers={ + "Access-Control-Allow-Origin": settings.CORS_ORIGINS_LIST, + "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", + "Access-Control-Allow-Headers": "Content-Type, Authorization, X-Tenant-ID", + "Access-Control-Allow-Credentials": "true", + "Access-Control-Max-Age": "86400" # Cache preflight for 24 hours + } + ) + try: # Get auth service URL (with service discovery if available) auth_url = await self._get_auth_service_url()