/** * Cookie Utilities * Handles cookie management for WebView authentication */ import CookieManager from '@react-native-cookies/cookies'; import { Platform } from 'react-native'; import { ALLOWED_DOMAIN, COOKIE_REFRESH_INTERVAL, INITIAL_COOKIE_DELAY } from './constants'; /** * Interface for cookie data */ export interface CookieData { [key: string]: any; } /** * Cookie Handler Class */ export class CookieHandler { private setWebViewCookies: (cookies: string | null) => void; constructor(setWebViewCookies: (cookies: string | null) => void) { this.setWebViewCookies = setWebViewCookies; } /** * Get WebView cookies for authentication * @returns Promise - Cookie string or null if not found */ async getWebViewCookies(): Promise { try { console.log('🍪 Requesting cookies using @react-native-cookies/cookies...'); const baseUrl = `${ALLOWED_DOMAIN}`; console.log('🍪 Getting cookies for URL:', baseUrl); let cookieString = ''; // Platform-specific cookie handling if (Platform.OS === 'ios') { // iOS: Can use getAll() try { const cookies = await CookieManager.getAll(); console.log('🍪 iOS - All cookies retrieved:', cookies); // Filter cookies for our domain const domainCookies = Object.keys(cookies).filter(key => key.includes(baseUrl) || key.includes(ALLOWED_DOMAIN.replace('/', '')) ); console.log('🍪 iOS - Domain cookies found:', domainCookies); for (const cookieKey of domainCookies) { const cookie = cookies[cookieKey]; console.log('🍪 iOS - Checking cookie:', cookieKey, cookie); if (cookie && typeof cookie === 'object') { const cookieValue = cookie.value || cookie; if (cookieValue && typeof cookieValue === 'string' && cookieValue.includes('session_id=')) { const sessionMatch = cookieValue.match(/session_id=([^;]+)/); if (sessionMatch) { console.log('✅ iOS - Found session_id in cookie:', sessionMatch[1]); } } if (typeof cookie === 'object' && cookie.name && cookie.value) { cookieString += `${cookie.name}=${cookie.value}; `; } else if (typeof cookie === 'string') { cookieString += cookie + '; '; } } } } catch (iosError) { console.log('⚠️ iOS getAll() failed, trying direct method:', iosError); } } // Both platforms: Try getting cookies directly for the domain try { console.log('🍪 Getting direct cookies for domain:', baseUrl); const directCookies = await CookieManager.get(baseUrl); console.log('🍪 Direct cookies for domain:', directCookies); if (directCookies && Object.keys(directCookies).length > 0) { // Convert to cookie string format const directCookieString = Object.entries(directCookies) .map(([name, value]) => `${name}=${value}`) .join('; '); console.log('🍪 Direct cookie string:', directCookieString); if (directCookieString && directCookieString.includes('session_id')) { cookieString = directCookieString; console.log('✅ Found session_id in direct cookies:', cookieString); } else { console.warn('⚠️ Direct cookies found but no session_id:', directCookieString); } } else { console.warn('⚠️ No direct cookies found for domain'); } } catch (directError) { console.log('⚠️ Could not get direct cookies:', directError); } // Fallback: Try getting cookies for the WebView URL try { const webViewUrl = `${ALLOWED_DOMAIN}/web`; console.log('🍪 Fallback - Getting cookies for WebView URL:', webViewUrl); const webViewCookies = await CookieManager.get(webViewUrl); console.log('🍪 WebView cookies:', webViewCookies); if (webViewCookies && Object.keys(webViewCookies).length > 0) { const webViewCookieString = Object.entries(webViewCookies) .map(([name, value]) => `${name}=${value}`) .join('; '); if (webViewCookieString && webViewCookieString.includes('session_id')) { cookieString = webViewCookieString; console.log('✅ Found session_id in WebView cookies:', cookieString); } } } catch (webViewError) { console.log('⚠️ Could not get WebView cookies:', webViewError); } if (cookieString && cookieString.includes('session_id')) { console.log('✅ Valid session cookies found:', cookieString); this.setWebViewCookies(cookieString); return cookieString; } else { console.warn('⚠️ No session_id found in any cookie method'); console.warn('⚠️ Final cookie string:', cookieString); this.setWebViewCookies(null); return null; } } catch (error) { console.error('❌ Error getting cookies with @react-native-cookies/cookies:', error); this.setWebViewCookies(null); return null; } } /** * Refresh WebView cookies periodically * @returns Function to clear the interval */ refreshWebViewCookies(): () => void { // Initial cookie request after a longer delay to ensure WebView is fully loaded and user is logged in setTimeout(() => { console.log('🔄 Initial cookie refresh after WebView load'); this.getWebViewCookies(); }, INITIAL_COOKIE_DELAY); // Set up periodic cookie refresh const cookieRefreshInterval = setInterval(() => { console.log('🔄 Periodic cookie refresh'); this.getWebViewCookies(); }, COOKIE_REFRESH_INTERVAL); // Return cleanup function return () => clearInterval(cookieRefreshInterval); } /** * Get cookies for a specific URL * @param url - URL to get cookies for * @returns Promise - Cookie data or null */ async getCookiesForUrl(url: string): Promise { try { console.log('🍪 Getting cookies for URL:', url); const cookies = await CookieManager.get(url); console.log('🍪 Cookies for URL:', cookies); return cookies; } catch (error) { console.error('❌ Error getting cookies for URL:', url, error); return null; } } /** * Set cookies for a specific URL * @param url - URL to set cookies for * @param cookies - Cookie data to set * @returns Promise - Success status */ async setCookiesForUrl(url: string, cookies: any): Promise { try { console.log('🍪 Setting cookies for URL:', url, cookies); await CookieManager.set(url, cookies); console.log('✅ Cookies set successfully for URL:', url); return true; } catch (error) { console.error('❌ Error setting cookies for URL:', url, error); return false; } } /** * Clear all cookies * @returns Promise - Success status */ async clearAllCookies(): Promise { try { console.log('🍪 Clearing all cookies'); await CookieManager.clearAll(); console.log('✅ All cookies cleared successfully'); this.setWebViewCookies(null); return true; } catch (error) { console.error('❌ Error clearing cookies:', error); return false; } } /** * Check if session cookies are valid * @param cookies - Cookie string to validate * @returns boolean - Whether cookies are valid */ isValidSessionCookie(cookies: string | null): boolean { if (!cookies) { return false; } const hasSessionId = cookies.includes('session_id='); const hasValidFormat = cookies.includes('=') && cookies.includes(';'); console.log('🍪 Cookie validation:', { hasSessionId, hasValidFormat, cookieLength: cookies.length }); return hasSessionId && hasValidFormat; } } /** * Create cookie handler instance */ export function createCookieHandler( setWebViewCookies: (cookies: string | null) => void ): CookieHandler { return new CookieHandler(setWebViewCookies); }