export interface TokenMessage { type: 'UM_AUTH_TOKEN'; token: string; refreshToken: string; } /** * Manages authentication tokens received from parent window (host) * Used by iframe modules to receive and store auth tokens */ class TokenManager { private token: string | null = null; private refreshToken: string | null = null; private tokenResolve: ((token: string) => void) | null = null; private tokenPromise: Promise; private isFramed: boolean; constructor() { // Check if we're running in an iframe this.isFramed = window.self !== window.top; // Create a promise that resolves when token is received this.tokenPromise = new Promise((resolve) => { this.tokenResolve = resolve; }); if (this.isFramed) { this.setupMessageListener(); // Request token after 2 seconds if not received setTimeout(() => { if (!this.token) { this.requestTokenFromHost(); } }, 2000); } } private setupMessageListener() { window.addEventListener('message', (event) => { // Security: Only accept from parent window if (event.source !== window.parent) { return; } const data = event.data as TokenMessage | undefined; if (data?.type === 'UM_AUTH_TOKEN') { this.token = data.token; this.refreshToken = data.refreshToken; // Store in localStorage for persistence localStorage.setItem('um_auth_token', data.token); localStorage.setItem('um_refresh_token', data.refreshToken); console.log('✅ Token received from host'); // Resolve the promise if (this.tokenResolve) { this.tokenResolve(data.token); } } }); } private requestTokenFromHost() { console.log('📤 Requesting token from host...'); window.parent.postMessage( { type: 'UM_REQUEST_AUTH' }, window.location.origin ); } /** * Get token - waits for it if not yet received */ async getToken(): Promise { if (this.token) { return this.token; } // Check localStorage as fallback const stored = localStorage.getItem('um_auth_token'); if (stored) { this.token = stored; return stored; } // Wait for token to arrive from parent return this.tokenPromise; } /** * Get token synchronously (returns null if not available) */ getTokenSync(): string | null { return this.token || localStorage.getItem('um_auth_token'); } getRefreshToken(): string | null { return this.refreshToken || localStorage.getItem('um_refresh_token'); } clearTokens() { this.token = null; this.refreshToken = null; localStorage.removeItem('um_auth_token'); localStorage.removeItem('um_refresh_token'); } isInFrame(): boolean { return this.isFramed; } } // Export singleton instance export const tokenManager = new TokenManager();