diff --git a/client/src/utils/api/apiClient.ts b/client/src/utils/api/apiClient.ts index 6072b85..aec0083 100644 --- a/client/src/utils/api/apiClient.ts +++ b/client/src/utils/api/apiClient.ts @@ -7,10 +7,20 @@ interface RequestOptions extends RequestInit { export class ApiClient { private static instance: ApiClient; private basePath: string; - private previousBasicAuth: string | null = null; + private static basicAuth: string | null = null; private constructor() { this.basePath = (window as any).__BASE_PATH__ || ''; + + if (document.cookie.includes('basicAuth=')) { + const base64Credentials = document.cookie + .split(';') + .find(row => row.trim().startsWith('basicAuth=')) + ?.split('=')[1]; + if (base64Credentials) { + ApiClient.basicAuth = `Basic ${base64Credentials}`; + } + } } static getInstance(): ApiClient { @@ -24,31 +34,33 @@ export class ApiClient { const headers = new Headers(options.headers); headers.set('Content-Type', 'application/json'); + if (ApiClient.basicAuth) { + headers.set('Authorization', ApiClient.basicAuth); + } + if (options.requiresAuth) { const token = localStorage.getItem('token'); if (token) { - headers.set('Authorization', `Bearer ${token}`); + if (ApiClient.basicAuth) { + headers.set('X-JWT-Token', `Bearer ${token}`); + } else { + headers.set('Authorization', `Bearer ${token}`); + } } } - const basicAuth = headers.get('Authorization')?.startsWith('Basic ') - ? headers.get('Authorization') - : null; - - if (basicAuth) { - this.previousBasicAuth = basicAuth; - } else if (this.previousBasicAuth && !options.requiresAuth) { - headers.set('Authorization', this.previousBasicAuth); - } - return headers; } private handleError(error: any): never { + console.error('API Client Error:', error); if (error instanceof Response) { if (error.status === 401 || error.status === 403) { const authHeader = error.headers.get('www-authenticate'); - if (authHeader?.includes('Bearer')) { + if (authHeader?.includes('Basic')) { + ApiClient.basicAuth = null; + document.cookie = 'basicAuth=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/'; + } else if (authHeader?.includes('Bearer')) { window.dispatchEvent(new CustomEvent(EVENTS.AUTH_ERROR)); } } @@ -64,16 +76,17 @@ export class ApiClient { credentials: 'include', }); - if (!response.ok) { - if (response.status === 401 || response.status === 403) { - const authHeader = response.headers.get('www-authenticate'); - if (authHeader?.includes('Bearer')) { - window.dispatchEvent(new CustomEvent(EVENTS.AUTH_ERROR)); - } + const authHeader = response.headers.get('www-authenticate'); + if (authHeader?.includes('Basic')) { + const authMatch = /Basic realm="([^"]+)"/.exec(authHeader); + if (authMatch) { + ApiClient.basicAuth = `Basic ${btoa(authMatch[1])}`; + document.cookie = `basicAuth=${btoa(authMatch[1])}; path=/; secure; samesite=strict`; } - const error = await response.json().catch(() => ({})); - error.status = response.status; - throw error; + } + + if (!response.ok) { + await this.handleError(response); } return response.json(); diff --git a/server/src/app.js b/server/src/app.js index c5a294d..cdcfb48 100644 --- a/server/src/app.js +++ b/server/src/app.js @@ -24,6 +24,37 @@ const basePath = process.env.BASE_PATH || ''; const buildPath = join(__dirname, '../../client/build'); const assetsPath = join(buildPath, 'assets'); +app.use((req, res, next) => { + Logger.debug('📨 Incoming request:', { + url: req.url, + method: req.method, + headers: { + ...req.headers, + authorization: req.headers.authorization, + 'x-forwarded-for': req.headers['x-forwarded-for'], + 'x-real-ip': req.headers['x-real-ip'], + host: req.headers.host, + cookie: req.headers.cookie, + } + }); + next(); +}); + +authRoutes.use((req, res, next) => { + Logger.debug('🔑 Auth route accessed:', { + url: req.url, + method: req.method, + headers: { + authorization: req.headers.authorization, + 'x-forwarded-for': req.headers['x-forwarded-for'], + 'x-real-ip': req.headers['x-real-ip'], + host: req.headers.host, + cookie: req.headers.cookie, + } + }); + next(); +}); + app.use(`${basePath}/api/auth`, authRoutes); app.use(`${basePath}/api/auth/oidc`, oidcRoutes); app.use(`${basePath}/api/snippets`, authenticateToken, snippetRoutes);