From 71587075c40cf334e2939bfb960511ae68347204 Mon Sep 17 00:00:00 2001 From: Egor Date: Sun, 18 Jan 2026 06:27:59 +0300 Subject: [PATCH] Update client.ts --- src/api/client.ts | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/api/client.ts b/src/api/client.ts index 782a924..808184c 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -6,6 +6,32 @@ const API_BASE_URL = import.meta.env.VITE_API_URL || '/api' // Настраиваем endpoint для refresh tokenRefreshManager.setRefreshEndpoint(`${API_BASE_URL}/cabinet/auth/refresh`) +// CSRF token management +const CSRF_COOKIE_NAME = 'csrf_token' +const CSRF_HEADER_NAME = 'X-CSRF-Token' + +function getCsrfToken(): string | null { + if (typeof document === 'undefined') return null + const match = document.cookie.match(new RegExp(`(^| )${CSRF_COOKIE_NAME}=([^;]+)`)) + return match ? match[2] : null +} + +function generateCsrfToken(): string { + const array = new Uint8Array(32) + crypto.getRandomValues(array) + return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('') +} + +function ensureCsrfToken(): string { + let token = getCsrfToken() + if (!token) { + token = generateCsrfToken() + // Set cookie with SameSite=Strict for CSRF protection + document.cookie = `${CSRF_COOKIE_NAME}=${token}; path=/; SameSite=Strict; Secure` + } + return token +} + const getTelegramInitData = (): string | null => { if (typeof window === 'undefined') return null @@ -51,6 +77,13 @@ apiClient.interceptors.request.use(async (config: InternalAxiosRequestConfig) => if (telegramInitData && config.headers) { config.headers['X-Telegram-Init-Data'] = telegramInitData } + + // Add CSRF token for state-changing methods + const method = config.method?.toUpperCase() + if (method && ['POST', 'PUT', 'DELETE', 'PATCH'].includes(method) && config.headers) { + config.headers[CSRF_HEADER_NAME] = ensureCsrfToken() + } + return config })