@omen.foundation/game-sdk 1.0.13 โ†’ 1.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -186,6 +186,7 @@ var OAuthFlow = class {
186
186
  }
187
187
  };
188
188
  immediateCheck();
189
+ console.log("[OAuthFlow] \u{1F504} Starting localStorage polling interval (every 100ms)");
189
190
  const pollInterval = setInterval(() => {
190
191
  pollCount++;
191
192
  const stored = localStorage.getItem(storageKey);
@@ -194,7 +195,8 @@ var OAuthFlow = class {
194
195
  key: storageKey.substring(0, 50) + "...",
195
196
  found: !!stored,
196
197
  pollCount,
197
- statePreview: state.substring(0, 20) + "..."
198
+ statePreview: state.substring(0, 20) + "...",
199
+ intervalActive: true
198
200
  });
199
201
  if (pollCount % 100 === 0) {
200
202
  immediateCheck();
@@ -373,11 +375,38 @@ var OAuthFlow = class {
373
375
  return false;
374
376
  }
375
377
  };
378
+ let popupClosedTime = null;
379
+ const POPUP_CLOSED_GRACE_PERIOD = 5e3;
376
380
  const checkClosed = setInterval(() => {
377
381
  if (messageReceived) {
382
+ clearInterval(checkClosed);
383
+ clearInterval(pollInterval);
378
384
  return;
379
385
  }
380
386
  if (isPopupActuallyClosed()) {
387
+ if (popupClosedTime === null) {
388
+ popupClosedTime = Date.now();
389
+ console.log("[OAuthFlow] \u26A0\uFE0F Popup appears closed, starting grace period for callback...", {
390
+ gracePeriod: `${POPUP_CLOSED_GRACE_PERIOD}ms`,
391
+ pollCount,
392
+ stillPolling: true
393
+ });
394
+ return;
395
+ }
396
+ const timeSinceClosed = Date.now() - popupClosedTime;
397
+ if (timeSinceClosed < POPUP_CLOSED_GRACE_PERIOD) {
398
+ console.log("[OAuthFlow] \u23F3 Popup closed, but still in grace period...", {
399
+ timeRemaining: `${POPUP_CLOSED_GRACE_PERIOD - timeSinceClosed}ms`,
400
+ pollCount
401
+ });
402
+ return;
403
+ }
404
+ console.log("[OAuthFlow] \u274C Popup closed and grace period expired without callback", {
405
+ timeSinceClosed: `${timeSinceClosed}ms`,
406
+ pollCount,
407
+ finalCheck: "Checking localStorage one last time..."
408
+ });
409
+ immediateCheck();
381
410
  clearInterval(checkClosed);
382
411
  clearInterval(pollInterval);
383
412
  window.removeEventListener("message", wrappedMessageListener);
@@ -391,6 +420,11 @@ var OAuthFlow = class {
391
420
  this.config.onError?.(error);
392
421
  reject(error);
393
422
  }
423
+ } else {
424
+ if (popupClosedTime !== null) {
425
+ console.log("[OAuthFlow] \u2705 Popup is open again (was temporarily on different origin)");
426
+ popupClosedTime = null;
427
+ }
394
428
  }
395
429
  }, 1e3);
396
430
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/pkce.ts","../src/oauth.ts","../src/iframe-auth.ts","../src/token-manager.ts","../src/sdk.ts","../src/server-sdk.ts"],"names":["codeVerifier"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * Generate PKCE (Proof Key for Code Exchange) code challenge and verifier\r\n */\r\nexport async function generatePKCE(): Promise<{ codeVerifier: string; codeChallenge: string }> {\r\n // Generate code verifier (43-128 characters, URL-safe)\r\n const codeVerifier = generateRandomString(128);\r\n\r\n // Generate code challenge (SHA256 hash of code verifier, base64url encoded)\r\n const hash = await sha256(codeVerifier);\r\n const codeChallenge = base64URLEncode(hash);\r\n\r\n return { codeVerifier, codeChallenge };\r\n}\r\n\r\n/**\r\n * Generate random URL-safe string\r\n */\r\nfunction generateRandomString(length: number): string {\r\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\r\n const array = new Uint8Array(length);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => charset[byte % charset.length]).join('');\r\n}\r\n\r\n/**\r\n * Base64 URL encode (without padding)\r\n */\r\nfunction base64URLEncode(buffer: ArrayBuffer): string {\r\n const base64 = btoa(String.fromCharCode(...new Uint8Array(buffer)));\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\r\n}\r\n\r\n/**\r\n * SHA256 hash\r\n */\r\nasync function sha256(message: string): Promise<ArrayBuffer> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(message);\r\n return crypto.subtle.digest('SHA-256', data);\r\n}\r\n","import type { OAuthOptions, OAuthTokenResponse } from './types';\r\nimport { generatePKCE } from './pkce';\r\n\r\ninterface OAuthFlowConfig {\r\n gameId: string;\r\n oauthAuthorizeUrl: string;\r\n oauthTokenUrl: string;\r\n apiBaseUrl: string;\r\n onTokenReceived: (tokenResponse: OAuthTokenResponse) => Promise<void>;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles OAuth 2.0 Authorization Code Grant flow with PKCE\r\n */\r\nexport class OAuthFlow {\r\n private config: OAuthFlowConfig;\r\n\r\n constructor(config: OAuthFlowConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<any> {\r\n // Generate state for CSRF protection\r\n const state = options.state || this.generateState();\r\n \r\n // CRITICAL: Clean up old OAuth callback entries from localStorage\r\n // This prevents state mismatches when starting a new flow\r\n try {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n console.log('[OAuthFlow] ๐Ÿงน Cleaning up old OAuth entries:', { count: allKeys.length });\r\n allKeys.forEach(key => {\r\n try {\r\n const data = localStorage.getItem(key);\r\n if (data) {\r\n const parsed = JSON.parse(data);\r\n const age = Date.now() - (parsed.timestamp || 0);\r\n // Remove entries older than 5 minutes\r\n if (age > 300000) {\r\n localStorage.removeItem(key);\r\n console.log('[OAuthFlow] ๐Ÿ—‘๏ธ Removed old entry:', key.substring(0, 50) + '...', { age: `${age}ms` });\r\n }\r\n }\r\n } catch (e) {\r\n // If we can't parse it, remove it anyway\r\n localStorage.removeItem(key);\r\n }\r\n });\r\n } catch (error) {\r\n console.warn('[OAuthFlow] โš ๏ธ Error cleaning up old entries:', error);\r\n }\r\n \r\n // Generate PKCE if enabled\r\n let codeChallenge: string | undefined;\r\n let codeVerifier: string | undefined;\r\n if (options.enablePKCE !== false) {\r\n const pkce = await generatePKCE();\r\n codeChallenge = pkce.codeChallenge;\r\n codeVerifier = pkce.codeVerifier;\r\n // Store code verifier for later use\r\n sessionStorage.setItem(`omenx_pkce_${state}`, codeVerifier);\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n // Build authorization URL\r\n const params = new URLSearchParams({\r\n client_id: this.config.gameId,\r\n redirect_uri: options.redirectUri,\r\n response_type: 'code',\r\n state: state,\r\n });\r\n\r\n if (codeChallenge) {\r\n params.append('code_challenge', codeChallenge);\r\n params.append('code_challenge_method', 'S256');\r\n }\r\n\r\n const authUrl = `${this.config.oauthAuthorizeUrl}?${params.toString()}`;\r\n\r\n // Open popup window\r\n const popup = window.open(\r\n authUrl,\r\n 'OmenX Authentication',\r\n 'width=500,height=600,left=' + (window.screen.width / 2 - 250) + ',top=' + (window.screen.height / 2 - 300)\r\n );\r\n\r\n if (!popup) {\r\n const error = new Error('Failed to open popup window. Please allow popups for this site.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Listen for authorization code\r\n const messageListener = async (event: MessageEvent) => {\r\n // Validate origin - the callback page is on the game's domain, not the OAuth server\r\n // We should check that the message comes from the same origin as the current window\r\n // (the game's domain where the callback page is hosted)\r\n try {\r\n // The callback page is on the game's domain, so check against current origin\r\n const currentOrigin = window.location.origin;\r\n if (event.origin !== currentOrigin) {\r\n // Message not from our domain - ignore it\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse the URL, skip origin check (development)\r\n }\r\n\r\n if (event.data?.type === 'OMENX_OAUTH_CODE') {\r\n window.removeEventListener('message', messageListener);\r\n popup.close();\r\n\r\n const { code, state: returnedState } = event.data;\r\n\r\n // Validate state\r\n if (returnedState !== state) {\r\n const error = new Error('Invalid state parameter. Possible CSRF attack.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n\r\n try {\r\n // Exchange code for token\r\n const tokenResponse = await this.exchangeCodeForToken(code, options.redirectUri, codeVerifier);\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n } catch (error) {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n }\r\n }\r\n };\r\n\r\n window.addEventListener('message', messageListener);\r\n\r\n // Also listen for localStorage events as fallback (in case window.opener is lost)\r\n // The callback page will store the code in localStorage if postMessage fails\r\n const storageListener = (event: StorageEvent) => {\r\n if (!event.key || !event.key.startsWith('omenx_oauth_callback_')) {\r\n return;\r\n }\r\n \r\n const callbackState = event.key.replace('omenx_oauth_callback_', '');\r\n if (callbackState !== state) {\r\n return; // Not our callback\r\n }\r\n \r\n try {\r\n const data = JSON.parse(event.newValue || '{}');\r\n if (data.code && data.state === state) {\r\n console.log('[OAuthFlow] Received OAuth code via localStorage fallback');\r\n messageReceived = true;\r\n window.removeEventListener('storage', storageListener);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n \r\n // Process the code the same way as postMessage\r\n const { code: codeFromStorage } = data;\r\n \r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n // Exchange code for token\r\n this.exchangeCodeForToken(codeFromStorage, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n \r\n // Clean up localStorage\r\n localStorage.removeItem(event.key!);\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] Error processing localStorage callback:', error);\r\n }\r\n };\r\n \r\n window.addEventListener('storage', storageListener);\r\n \r\n // Also poll localStorage as additional fallback (storage events don't fire in same window)\r\n // This is critical because when the popup closes, storage events might not fire\r\n let pollCount = 0;\r\n const storageKey = `omenx_oauth_callback_${state}`;\r\n \r\n // Immediately check localStorage on first poll (before interval starts)\r\n // This helps catch callback data that was stored before polling started\r\n const immediateCheck = () => {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n console.log('[OAuthFlow] ๐Ÿ” Immediate localStorage check:', { \r\n count: allKeys.length,\r\n keys: allKeys.map(k => k.substring(0, 50) + '...'),\r\n lookingFor: storageKey.substring(0, 50) + '...',\r\n expectedState: state.substring(0, 20) + '...'\r\n });\r\n \r\n // Try to find a match by checking each key\r\n for (const key of allKeys) {\r\n const storedData = localStorage.getItem(key);\r\n if (storedData) {\r\n try {\r\n const data = JSON.parse(storedData);\r\n console.log('[OAuthFlow] ๐Ÿ” Checking stored key:', {\r\n key: key.substring(0, 50) + '...',\r\n storedState: data.state?.substring(0, 20) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n statesMatch: data.state === state,\r\n hasCode: !!data.code,\r\n timestamp: data.timestamp,\r\n age: data.timestamp ? `${Date.now() - data.timestamp}ms` : 'unknown'\r\n });\r\n } catch (e) {\r\n console.warn('[OAuthFlow] โš ๏ธ Error parsing stored key:', key, e);\r\n }\r\n }\r\n }\r\n };\r\n \r\n // Run immediate check\r\n immediateCheck();\r\n \r\n const pollInterval = setInterval(() => {\r\n pollCount++;\r\n const stored = localStorage.getItem(storageKey);\r\n \r\n // Log every 1 second (10 * 100ms) for debugging\r\n if (pollCount % 10 === 0) {\r\n console.log('[OAuthFlow] ๐Ÿ” Polling localStorage...', { \r\n key: storageKey.substring(0, 50) + '...',\r\n found: !!stored, \r\n pollCount,\r\n statePreview: state.substring(0, 20) + '...'\r\n });\r\n \r\n // Re-check all keys every 10 seconds for debugging\r\n if (pollCount % 100 === 0) {\r\n immediateCheck();\r\n }\r\n }\r\n \r\n // ALWAYS check if we found the data (not just log every 10 polls)\r\n if (stored) {\r\n try {\r\n const data = JSON.parse(stored);\r\n \r\n // Log immediately when we find data (not just every 10 polls)\r\n if (pollCount === 1 || pollCount % 10 === 0) {\r\n console.log('[OAuthFlow] โœ… Found stored data!', { \r\n hasCode: !!data.code,\r\n hasState: !!data.state,\r\n stateMatch: data.state === state,\r\n storedState: data.state?.substring(0, 20) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n pollCount\r\n });\r\n }\r\n \r\n if (data.code && data.state === state) {\r\n const age = Date.now() - (data.timestamp || 0);\r\n if (age < 30000) { // 30 second timeout\r\n console.log('[OAuthFlow] โœ…โœ…โœ… Processing OAuth callback from localStorage!', { \r\n age: `${age}ms`, \r\n hasCode: !!data.code,\r\n codePreview: data.code.substring(0, 10) + '...',\r\n pollCount\r\n });\r\n // Found callback data, trigger storage event manually\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n // Note: broadcastChannel cleanup will happen in checkClosed interval\r\n storageListener(new StorageEvent('storage', {\r\n key: storageKey,\r\n newValue: stored,\r\n storageArea: localStorage,\r\n }));\r\n return; // Exit early to prevent further processing\r\n } else {\r\n console.warn('[OAuthFlow] โš ๏ธ Callback data too old, removing:', { age: `${age}ms` });\r\n localStorage.removeItem(storageKey);\r\n }\r\n } else {\r\n // Log state mismatch immediately when found\r\n console.warn('[OAuthFlow] โš ๏ธ State mismatch!', {\r\n storedState: data.state?.substring(0, 20) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n statesMatch: data.state === state,\r\n storedStateLength: data.state?.length,\r\n expectedStateLength: state.length,\r\n pollCount\r\n });\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] โŒ Error parsing localStorage callback:', error, { \r\n stored: stored?.substring(0, 100) + '...',\r\n pollCount \r\n });\r\n }\r\n } else {\r\n // Also check for ANY omenx_oauth_callback keys if we haven't found our specific key\r\n // This helps catch cases where the key format is slightly different\r\n // Check more frequently (every 5 polls = 500ms) to catch the callback quickly\r\n if (pollCount === 1 || pollCount % 5 === 0) {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n if (allKeys.length > 0) {\r\n console.log('[OAuthFlow] ๐Ÿ” Found localStorage keys (checking all for state match):', { \r\n count: allKeys.length,\r\n keys: allKeys.map(k => k.substring(0, 50) + '...'),\r\n lookingFor: storageKey.substring(0, 50) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n pollCount\r\n });\r\n \r\n // Check each key to see if any match our state (by value, not just key name)\r\n for (const key of allKeys) {\r\n const storedData = localStorage.getItem(key);\r\n if (storedData) {\r\n try {\r\n const data = JSON.parse(storedData);\r\n const statesMatch = data.state === state;\r\n console.log('[OAuthFlow] ๐Ÿ” Checking stored key:', {\r\n key: key.substring(0, 50) + '...',\r\n storedState: data.state?.substring(0, 20) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n statesMatch: statesMatch,\r\n storedStateLength: data.state?.length,\r\n expectedStateLength: state.length,\r\n hasCode: !!data.code,\r\n pollCount\r\n });\r\n \r\n // If state matches, process it even if the key name doesn't match exactly\r\n if (statesMatch && data.code) {\r\n const age = Date.now() - (data.timestamp || 0);\r\n if (age < 30000) {\r\n console.log('[OAuthFlow] โœ…โœ…โœ… Found matching state in different key! Processing...', {\r\n key: key.substring(0, 50) + '...',\r\n age: `${age}ms`,\r\n pollCount\r\n });\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n // Process the callback\r\n storageListener(new StorageEvent('storage', {\r\n key: key,\r\n newValue: storedData,\r\n storageArea: localStorage,\r\n }));\r\n return;\r\n }\r\n }\r\n } catch (e) {\r\n console.warn('[OAuthFlow] โš ๏ธ Error parsing key:', key, e);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }, 100); // Poll every 100ms\r\n \r\n // Also listen for BroadcastChannel as another fallback\r\n let broadcastChannel: BroadcastChannel | null = null;\r\n try {\r\n broadcastChannel = new BroadcastChannel('omenx_oauth');\r\n const broadcastListener = (event: MessageEvent) => {\r\n if (event.data?.type === 'OMENX_OAUTH_CODE' && event.data?.state === state) {\r\n console.log('[OAuthFlow] โœ… Received OAuth code via BroadcastChannel');\r\n messageReceived = true;\r\n clearInterval(pollInterval);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n \r\n const { code: codeFromBroadcast } = event.data;\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n this.exchangeCodeForToken(codeFromBroadcast, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n }\r\n };\r\n // BroadcastChannel uses onmessage, not addEventListener\r\n broadcastChannel.onmessage = broadcastListener;\r\n \r\n // Clean up will happen in checkClosed interval\r\n } catch (error) {\r\n console.warn('[OAuthFlow] BroadcastChannel not supported:', error);\r\n broadcastChannel = null;\r\n }\r\n \r\n // Log that we're starting to listen for OAuth callback\r\n console.log('[OAuthFlow] ๐Ÿ” Starting OAuth flow, listening for callback...', { \r\n state: state,\r\n statePreview: state.substring(0, 20) + '...',\r\n stateLength: state.length,\r\n hasOpener: !!window.opener,\r\n polling: true,\r\n broadcastChannel: true,\r\n expectedKey: `omenx_oauth_callback_${state}`\r\n });\r\n \r\n // Check if popup was closed\r\n // Only report cancellation if we haven't received a message yet\r\n let messageReceived = false;\r\n const originalMessageListener = messageListener;\r\n const wrappedMessageListener = async (event: MessageEvent) => {\r\n messageReceived = true;\r\n // Clean up listeners when message is received\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n await originalMessageListener(event);\r\n };\r\n window.removeEventListener('message', messageListener);\r\n window.addEventListener('message', wrappedMessageListener);\r\n \r\n /**\r\n * Check if popup is actually closed (not just on a different origin)\r\n * When a popup navigates to a different domain, popup.closed might be true\r\n * due to cross-origin restrictions, but the popup is still open.\r\n * We can detect this by trying to access popup.location - if it throws,\r\n * the popup is still open but on a different origin.\r\n */\r\n const isPopupActuallyClosed = (): boolean => {\r\n try {\r\n // If popup.closed is false, it's definitely still open\r\n if (!popup.closed) {\r\n return false;\r\n }\r\n \r\n // If popup.closed is true, we need to verify it's actually closed\r\n // by trying to access its location\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n const _ = popup.location.href;\r\n // If we can access location, popup is on same origin and closed\r\n return true;\r\n } catch (e) {\r\n // If accessing location throws, popup is on different origin (still open)\r\n // This is normal during OAuth flow when popup navigates to OAuth server\r\n return false;\r\n }\r\n } catch (e) {\r\n // If we can't check at all, assume popup is still open to be safe\r\n return false;\r\n }\r\n };\r\n \r\n const checkClosed = setInterval(() => {\r\n // Skip check if we've already received a message\r\n if (messageReceived) {\r\n return;\r\n }\r\n \r\n // Check if popup is actually closed (handles cross-origin correctly)\r\n if (isPopupActuallyClosed()) {\r\n clearInterval(checkClosed);\r\n clearInterval(pollInterval);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n // Only report cancellation if we haven't received a message\r\n if (!messageReceived) {\r\n const error = new Error('Authentication was cancelled.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n }\r\n }\r\n }, 1000);\r\n });\r\n }\r\n\r\n /**\r\n * Exchange authorization code for access token\r\n */\r\n private async exchangeCodeForToken(\r\n code: string,\r\n redirectUri: string,\r\n codeVerifier?: string\r\n ): Promise<OAuthTokenResponse> {\r\n const body: any = {\r\n code,\r\n redirect_uri: redirectUri,\r\n grant_type: 'authorization_code',\r\n };\r\n\r\n if (codeVerifier) {\r\n body.code_verifier = codeVerifier;\r\n }\r\n\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n // Note: API key should be included via Authorization header\r\n // This should be set by the game's backend, not the SDK\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({ message: 'Failed to exchange code for token' }));\r\n throw new Error(error.message || 'Failed to exchange code for token');\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Generate random state for CSRF protection\r\n */\r\n private generateState(): string {\r\n const array = new Uint8Array(32);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\ninterface IframeAuthConfig {\r\n gameId: string;\r\n parentOrigin?: string;\r\n onAuth: (authData: AuthData) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles authentication data passed from parent window via postMessage\r\n */\r\nexport class IframeAuth {\r\n private config: IframeAuthConfig;\r\n private messageListener: ((event: MessageEvent) => void) | null = null;\r\n\r\n constructor(config: IframeAuthConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Initialize iframe authentication listener\r\n */\r\n init(): void {\r\n // Request auth data from parent\r\n this.requestAuth();\r\n\r\n // Listen for auth data from parent\r\n this.messageListener = (event: MessageEvent) => {\r\n // Validate origin if specified\r\n if (this.config.parentOrigin) {\r\n try {\r\n const parentUrl = new URL(this.config.parentOrigin);\r\n if (event.origin !== parentUrl.origin) {\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse parent origin, skip validation (development)\r\n }\r\n }\r\n\r\n // Handle auth data\r\n if (event.data?.type === 'OMENX_AUTH') {\r\n const authData = event.data.payload as AuthData;\r\n\r\n // Validate game ID\r\n if (authData.gameId !== this.config.gameId) {\r\n this.config.onError?.(new Error(`Game ID mismatch. Expected ${this.config.gameId}, got ${authData.gameId}`));\r\n return;\r\n }\r\n\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onError?.(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n this.config.onAuth(authData);\r\n }\r\n };\r\n\r\n window.addEventListener('message', this.messageListener);\r\n }\r\n\r\n /**\r\n * Request authentication data from parent window\r\n */\r\n private requestAuth(): void {\r\n if (window.parent === window) {\r\n // Not in an iframe\r\n return;\r\n }\r\n\r\n // Send request to parent\r\n const parentOrigin = this.config.parentOrigin || '*';\r\n window.parent.postMessage(\r\n {\r\n type: 'OMENX_AUTH_REQUEST',\r\n gameId: this.config.gameId,\r\n },\r\n parentOrigin\r\n );\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy(): void {\r\n if (this.messageListener) {\r\n window.removeEventListener('message', this.messageListener);\r\n this.messageListener = null;\r\n }\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\n/**\r\n * Manages token storage and retrieval\r\n */\r\nexport class TokenManager {\r\n private storageKeyPrefix: string;\r\n\r\n constructor(storageKeyPrefix: string = 'omenx_game_') {\r\n this.storageKeyPrefix = storageKeyPrefix;\r\n }\r\n\r\n /**\r\n * Store authentication data\r\n */\r\n storeAuth(authData: AuthData, refreshToken: string, expiresIn: number): void {\r\n try {\r\n localStorage.setItem(`${this.storageKeyPrefix}auth`, JSON.stringify(authData));\r\n localStorage.setItem(`${this.storageKeyPrefix}refresh_token`, refreshToken);\r\n localStorage.setItem(`${this.storageKeyPrefix}expires_at`, String(Date.now() + (expiresIn * 1000)));\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to store auth data:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Get stored authentication data\r\n */\r\n getStoredAuth(): AuthData | null {\r\n try {\r\n const stored = localStorage.getItem(`${this.storageKeyPrefix}auth`);\r\n if (!stored) {\r\n return null;\r\n }\r\n return JSON.parse(stored) as AuthData;\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve auth data:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get stored refresh token\r\n */\r\n getRefreshToken(): string | null {\r\n try {\r\n return localStorage.getItem(`${this.storageKeyPrefix}refresh_token`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve refresh token:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Clear all stored authentication data\r\n */\r\n clearStorage(): void {\r\n try {\r\n localStorage.removeItem(`${this.storageKeyPrefix}auth`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}refresh_token`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}expires_at`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to clear storage:', error);\r\n }\r\n }\r\n}\r\n","import type {\r\n OmenXGameSDKConfig,\r\n AuthData,\r\n OAuthOptions,\r\n OAuthTokenResponse,\r\n ApiCallOptions,\r\n} from './types';\r\nimport { OAuthFlow } from './oauth';\r\nimport { IframeAuth } from './iframe-auth';\r\nimport { TokenManager } from './token-manager';\r\n\r\n/**\r\n * OmenX Game SDK\r\n * \r\n * Provides authentication and API integration for games on the OmenX platform.\r\n * Supports both OAuth-style authentication and iframe authentication passing.\r\n */\r\nexport class OmenXGameSDK {\r\n private config: Required<OmenXGameSDKConfig>;\r\n private oauthFlow: OAuthFlow;\r\n private iframeAuth: IframeAuth | null = null;\r\n private tokenManager: TokenManager;\r\n private currentAuthData: AuthData | null = null;\r\n\r\n constructor(config: OmenXGameSDKConfig) {\r\n // Set defaults\r\n const apiBaseUrl = config.apiBaseUrl || 'https://api.omen.foundation';\r\n this.config = {\r\n gameId: config.gameId,\r\n apiBaseUrl: apiBaseUrl,\r\n oauthAuthorizeUrl: config.oauthAuthorizeUrl || `${apiBaseUrl}/v1/oauth/authorize`,\r\n oauthTokenUrl: config.oauthTokenUrl || `${apiBaseUrl}/v1/oauth/token`,\r\n onAuth: config.onAuth || (() => {}),\r\n onAuthError: config.onAuthError || ((error) => console.error('[OmenX SDK] Auth error:', error)),\r\n onLogout: config.onLogout || (() => {}),\r\n enableIframeAuth: config.enableIframeAuth !== false,\r\n parentOrigin: config.parentOrigin ?? '',\r\n storageKeyPrefix: config.storageKeyPrefix || 'omenx_game_',\r\n };\r\n\r\n // Initialize components\r\n this.tokenManager = new TokenManager(this.config.storageKeyPrefix);\r\n this.oauthFlow = new OAuthFlow({\r\n gameId: this.config.gameId,\r\n oauthAuthorizeUrl: this.config.oauthAuthorizeUrl,\r\n oauthTokenUrl: this.config.oauthTokenUrl,\r\n apiBaseUrl: this.config.apiBaseUrl,\r\n onTokenReceived: this.handleTokenReceived.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n\r\n if (this.config.enableIframeAuth) {\r\n this.iframeAuth = new IframeAuth({\r\n gameId: this.config.gameId,\r\n parentOrigin: this.config.parentOrigin || undefined,\r\n onAuth: this.handleAuthData.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Initialize the SDK\r\n * Call this after creating an instance\r\n */\r\n async init(): Promise<void> {\r\n // Try to restore from stored token\r\n const storedAuth = this.tokenManager.getStoredAuth();\r\n if (storedAuth) {\r\n // Check if token is still valid (not expired)\r\n const expiresAt = storedAuth.timestamp + (3600 * 1000); // 1 hour default\r\n if (Date.now() < expiresAt) {\r\n this.currentAuthData = storedAuth;\r\n this.config.onAuth(storedAuth);\r\n return;\r\n } else {\r\n // Token expired, try to refresh\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n return;\r\n } catch (error) {\r\n // Refresh failed, clear storage\r\n this.tokenManager.clearStorage();\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If iframe auth is enabled, try to get auth from parent\r\n if (this.config.enableIframeAuth && this.iframeAuth !== null) {\r\n this.iframeAuth.init();\r\n }\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<AuthData> {\r\n return this.oauthFlow.authenticate(options);\r\n }\r\n\r\n /**\r\n * Get current authentication data\r\n */\r\n getAuthData(): AuthData | null {\r\n return this.currentAuthData;\r\n }\r\n\r\n /**\r\n * Check if user is authenticated\r\n */\r\n isAuthenticated(): boolean {\r\n return this.currentAuthData !== null;\r\n }\r\n\r\n /**\r\n * Logout user\r\n */\r\n async logout(): Promise<void> {\r\n // Revoke token if we have one\r\n if (this.currentAuthData?.accessToken) {\r\n try {\r\n await this.apiCall('/v1/oauth/revoke', {\r\n method: 'POST',\r\n body: { token: this.currentAuthData.accessToken },\r\n includeAuth: false, // Don't include auth header for revoke\r\n });\r\n } catch (error) {\r\n // Ignore errors on revoke\r\n console.warn('[OmenX SDK] Failed to revoke token:', error);\r\n }\r\n }\r\n\r\n // Clear local state\r\n this.currentAuthData = null;\r\n this.tokenManager.clearStorage();\r\n this.config.onLogout();\r\n }\r\n\r\n /**\r\n * Make an authenticated API call\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...options.headers,\r\n };\r\n\r\n // Add authentication header if needed\r\n if (options.includeAuth !== false && this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n }\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n // If unauthorized, try to refresh token\r\n if (response.status === 401 && this.currentAuthData) {\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n // Retry the request with new token\r\n if (this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n return fetch(url, { ...fetchOptions, headers });\r\n }\r\n } catch (error) {\r\n // Refresh failed, logout\r\n await this.logout();\r\n throw new Error('Authentication expired. Please login again.');\r\n }\r\n }\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Handle token received from OAuth flow\r\n */\r\n private async handleTokenReceived(tokenResponse: OAuthTokenResponse): Promise<void> {\r\n const authData: AuthData = {\r\n accessToken: tokenResponse.access_token,\r\n walletAddress: tokenResponse.user.walletAddress,\r\n userId: tokenResponse.user.userId,\r\n profileName: tokenResponse.user.profileName,\r\n profilePicture: tokenResponse.user.profilePicture,\r\n email: tokenResponse.user.email,\r\n gameId: this.config.gameId,\r\n timestamp: Date.now(),\r\n };\r\n\r\n // Store tokens\r\n this.tokenManager.storeAuth(authData, tokenResponse.refresh_token, tokenResponse.expires_in);\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Handle auth data from iframe\r\n */\r\n private handleAuthData(authData: AuthData): void {\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onAuthError(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Refresh access token using refresh token\r\n */\r\n private async refreshAccessToken(refreshToken: string): Promise<void> {\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n grant_type: 'refresh_token',\r\n refresh_token: refreshToken,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error('Failed to refresh token');\r\n }\r\n\r\n const tokenResponse: OAuthTokenResponse = await response.json();\r\n await this.handleTokenReceived(tokenResponse);\r\n }\r\n}\r\n","import type { ApiCallOptions } from './types';\r\n\r\ninterface ServerSDKConfig {\r\n /**\r\n * Your developer API key (from developer portal)\r\n */\r\n apiKey: string;\r\n\r\n /**\r\n * OmenX API base URL (default: https://api.omen.foundation)\r\n */\r\n apiBaseUrl?: string;\r\n}\r\n\r\n/**\r\n * OmenX Game SDK - Server Mode\r\n * \r\n * For Node.js backends using developer API keys.\r\n * This mode allows server-to-server communication with the OmenX API.\r\n */\r\nexport class OmenXServerSDK {\r\n private config: Required<ServerSDKConfig>;\r\n private apiKey: string;\r\n\r\n constructor(config: ServerSDKConfig) {\r\n this.apiKey = config.apiKey;\r\n this.config = {\r\n apiKey: config.apiKey,\r\n apiBaseUrl: config.apiBaseUrl || 'https://api.omen.foundation',\r\n };\r\n }\r\n\r\n /**\r\n * Make an authenticated API call using the developer API key\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.apiKey}`,\r\n ...options.headers,\r\n };\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => 'Unknown error');\r\n throw new Error(`API call failed: ${response.status} ${response.statusText} - ${errorText}`);\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Health check\r\n */\r\n async healthCheck(): Promise<any> {\r\n const response = await this.apiCall('/v1/health', { includeAuth: false });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get API key information\r\n */\r\n async getApiKeyInfo(): Promise<any> {\r\n const response = await this.apiCall('/v1/auth/me');\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Player Operations\r\n */\r\n\r\n /**\r\n * Get native and ERC20 token balances for a wallet\r\n */\r\n async getPlayerBalances(wallet: string, chainId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/players/${wallet}/balances?chainId=${chainId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get paginated NFTs for a wallet\r\n */\r\n async getPlayerNfts(\r\n wallet: string,\r\n chainId: string,\r\n options?: {\r\n contract?: string;\r\n cursor?: string;\r\n limit?: number;\r\n }\r\n ): Promise<any> {\r\n const params = new URLSearchParams({ chainId });\r\n if (options?.contract) params.append('contract', options.contract);\r\n if (options?.cursor) params.append('cursor', options.cursor);\r\n if (options?.limit) params.append('limit', options.limit.toString());\r\n \r\n const response = await this.apiCall(`/v1/players/${wallet}/nfts?${params.toString()}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Purchase Operations\r\n */\r\n\r\n /**\r\n * Create a server-authoritative purchase\r\n */\r\n async createPurchase(params: {\r\n playerWallet?: string;\r\n walletAddress?: string; // Legacy field name\r\n skuId?: string;\r\n sku?: string; // Legacy field name\r\n quantity?: number;\r\n idempotencyKey?: string;\r\n paymentMethod?: string;\r\n metadata?: Record<string, any>;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/purchases', {\r\n method: 'POST',\r\n body: params,\r\n headers: params.idempotencyKey ? {\r\n 'Idempotency-Key': params.idempotencyKey,\r\n } : undefined,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * NFT Template Operations\r\n */\r\n\r\n /**\r\n * Get all NFT templates for a game\r\n */\r\n async getNftTemplates(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/templates?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get NFT contract address for a game\r\n */\r\n async getNftContract(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/contract?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Mint NFTs (single or batch)\r\n */\r\n async mintNfts(params: {\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch mint NFTs\r\n */\r\n async batchMintNfts(mints: Array<{\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }>): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint/batch', {\r\n method: 'POST',\r\n body: { mints },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Update NFT metadata\r\n */\r\n async updateNftMetadata(\r\n tokenId: string,\r\n metadata: {\r\n attributes?: Record<string, string | number | boolean>;\r\n name?: string;\r\n description?: string;\r\n imageUrl?: string;\r\n }\r\n ): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}/metadata`, {\r\n method: 'PUT',\r\n body: metadata,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Burn NFT (single)\r\n */\r\n async burnNft(tokenId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}`, {\r\n method: 'DELETE',\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch burn NFTs\r\n */\r\n async batchBurnNfts(tokenIds: string[]): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/burn/batch', {\r\n method: 'POST',\r\n body: { tokenIds },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Pack opener - mint random NFTs from a drop table\r\n */\r\n async packOpener(params: {\r\n dropTableId: string;\r\n recipientAddress: string;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/pack-opener', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n}\r\n"]}
1
+ {"version":3,"sources":["../src/pkce.ts","../src/oauth.ts","../src/iframe-auth.ts","../src/token-manager.ts","../src/sdk.ts","../src/server-sdk.ts"],"names":["codeVerifier"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * Generate PKCE (Proof Key for Code Exchange) code challenge and verifier\r\n */\r\nexport async function generatePKCE(): Promise<{ codeVerifier: string; codeChallenge: string }> {\r\n // Generate code verifier (43-128 characters, URL-safe)\r\n const codeVerifier = generateRandomString(128);\r\n\r\n // Generate code challenge (SHA256 hash of code verifier, base64url encoded)\r\n const hash = await sha256(codeVerifier);\r\n const codeChallenge = base64URLEncode(hash);\r\n\r\n return { codeVerifier, codeChallenge };\r\n}\r\n\r\n/**\r\n * Generate random URL-safe string\r\n */\r\nfunction generateRandomString(length: number): string {\r\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\r\n const array = new Uint8Array(length);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => charset[byte % charset.length]).join('');\r\n}\r\n\r\n/**\r\n * Base64 URL encode (without padding)\r\n */\r\nfunction base64URLEncode(buffer: ArrayBuffer): string {\r\n const base64 = btoa(String.fromCharCode(...new Uint8Array(buffer)));\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\r\n}\r\n\r\n/**\r\n * SHA256 hash\r\n */\r\nasync function sha256(message: string): Promise<ArrayBuffer> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(message);\r\n return crypto.subtle.digest('SHA-256', data);\r\n}\r\n","import type { OAuthOptions, OAuthTokenResponse } from './types';\r\nimport { generatePKCE } from './pkce';\r\n\r\ninterface OAuthFlowConfig {\r\n gameId: string;\r\n oauthAuthorizeUrl: string;\r\n oauthTokenUrl: string;\r\n apiBaseUrl: string;\r\n onTokenReceived: (tokenResponse: OAuthTokenResponse) => Promise<void>;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles OAuth 2.0 Authorization Code Grant flow with PKCE\r\n */\r\nexport class OAuthFlow {\r\n private config: OAuthFlowConfig;\r\n\r\n constructor(config: OAuthFlowConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<any> {\r\n // Generate state for CSRF protection\r\n const state = options.state || this.generateState();\r\n \r\n // CRITICAL: Clean up old OAuth callback entries from localStorage\r\n // This prevents state mismatches when starting a new flow\r\n try {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n console.log('[OAuthFlow] ๐Ÿงน Cleaning up old OAuth entries:', { count: allKeys.length });\r\n allKeys.forEach(key => {\r\n try {\r\n const data = localStorage.getItem(key);\r\n if (data) {\r\n const parsed = JSON.parse(data);\r\n const age = Date.now() - (parsed.timestamp || 0);\r\n // Remove entries older than 5 minutes\r\n if (age > 300000) {\r\n localStorage.removeItem(key);\r\n console.log('[OAuthFlow] ๐Ÿ—‘๏ธ Removed old entry:', key.substring(0, 50) + '...', { age: `${age}ms` });\r\n }\r\n }\r\n } catch (e) {\r\n // If we can't parse it, remove it anyway\r\n localStorage.removeItem(key);\r\n }\r\n });\r\n } catch (error) {\r\n console.warn('[OAuthFlow] โš ๏ธ Error cleaning up old entries:', error);\r\n }\r\n \r\n // Generate PKCE if enabled\r\n let codeChallenge: string | undefined;\r\n let codeVerifier: string | undefined;\r\n if (options.enablePKCE !== false) {\r\n const pkce = await generatePKCE();\r\n codeChallenge = pkce.codeChallenge;\r\n codeVerifier = pkce.codeVerifier;\r\n // Store code verifier for later use\r\n sessionStorage.setItem(`omenx_pkce_${state}`, codeVerifier);\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n // Build authorization URL\r\n const params = new URLSearchParams({\r\n client_id: this.config.gameId,\r\n redirect_uri: options.redirectUri,\r\n response_type: 'code',\r\n state: state,\r\n });\r\n\r\n if (codeChallenge) {\r\n params.append('code_challenge', codeChallenge);\r\n params.append('code_challenge_method', 'S256');\r\n }\r\n\r\n const authUrl = `${this.config.oauthAuthorizeUrl}?${params.toString()}`;\r\n\r\n // Open popup window\r\n const popup = window.open(\r\n authUrl,\r\n 'OmenX Authentication',\r\n 'width=500,height=600,left=' + (window.screen.width / 2 - 250) + ',top=' + (window.screen.height / 2 - 300)\r\n );\r\n\r\n if (!popup) {\r\n const error = new Error('Failed to open popup window. Please allow popups for this site.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Listen for authorization code\r\n const messageListener = async (event: MessageEvent) => {\r\n // Validate origin - the callback page is on the game's domain, not the OAuth server\r\n // We should check that the message comes from the same origin as the current window\r\n // (the game's domain where the callback page is hosted)\r\n try {\r\n // The callback page is on the game's domain, so check against current origin\r\n const currentOrigin = window.location.origin;\r\n if (event.origin !== currentOrigin) {\r\n // Message not from our domain - ignore it\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse the URL, skip origin check (development)\r\n }\r\n\r\n if (event.data?.type === 'OMENX_OAUTH_CODE') {\r\n window.removeEventListener('message', messageListener);\r\n popup.close();\r\n\r\n const { code, state: returnedState } = event.data;\r\n\r\n // Validate state\r\n if (returnedState !== state) {\r\n const error = new Error('Invalid state parameter. Possible CSRF attack.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n\r\n try {\r\n // Exchange code for token\r\n const tokenResponse = await this.exchangeCodeForToken(code, options.redirectUri, codeVerifier);\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n } catch (error) {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n }\r\n }\r\n };\r\n\r\n window.addEventListener('message', messageListener);\r\n\r\n // Also listen for localStorage events as fallback (in case window.opener is lost)\r\n // The callback page will store the code in localStorage if postMessage fails\r\n const storageListener = (event: StorageEvent) => {\r\n if (!event.key || !event.key.startsWith('omenx_oauth_callback_')) {\r\n return;\r\n }\r\n \r\n const callbackState = event.key.replace('omenx_oauth_callback_', '');\r\n if (callbackState !== state) {\r\n return; // Not our callback\r\n }\r\n \r\n try {\r\n const data = JSON.parse(event.newValue || '{}');\r\n if (data.code && data.state === state) {\r\n console.log('[OAuthFlow] Received OAuth code via localStorage fallback');\r\n messageReceived = true;\r\n window.removeEventListener('storage', storageListener);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n \r\n // Process the code the same way as postMessage\r\n const { code: codeFromStorage } = data;\r\n \r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n // Exchange code for token\r\n this.exchangeCodeForToken(codeFromStorage, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n \r\n // Clean up localStorage\r\n localStorage.removeItem(event.key!);\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] Error processing localStorage callback:', error);\r\n }\r\n };\r\n \r\n window.addEventListener('storage', storageListener);\r\n \r\n // Also poll localStorage as additional fallback (storage events don't fire in same window)\r\n // This is critical because when the popup closes, storage events might not fire\r\n let pollCount = 0;\r\n const storageKey = `omenx_oauth_callback_${state}`;\r\n \r\n // Immediately check localStorage on first poll (before interval starts)\r\n // This helps catch callback data that was stored before polling started\r\n const immediateCheck = () => {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n console.log('[OAuthFlow] ๐Ÿ” Immediate localStorage check:', { \r\n count: allKeys.length,\r\n keys: allKeys.map(k => k.substring(0, 50) + '...'),\r\n lookingFor: storageKey.substring(0, 50) + '...',\r\n expectedState: state.substring(0, 20) + '...'\r\n });\r\n \r\n // Try to find a match by checking each key\r\n for (const key of allKeys) {\r\n const storedData = localStorage.getItem(key);\r\n if (storedData) {\r\n try {\r\n const data = JSON.parse(storedData);\r\n console.log('[OAuthFlow] ๐Ÿ” Checking stored key:', {\r\n key: key.substring(0, 50) + '...',\r\n storedState: data.state?.substring(0, 20) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n statesMatch: data.state === state,\r\n hasCode: !!data.code,\r\n timestamp: data.timestamp,\r\n age: data.timestamp ? `${Date.now() - data.timestamp}ms` : 'unknown'\r\n });\r\n } catch (e) {\r\n console.warn('[OAuthFlow] โš ๏ธ Error parsing stored key:', key, e);\r\n }\r\n }\r\n }\r\n };\r\n \r\n // Run immediate check\r\n immediateCheck();\r\n \r\n // Log that polling is starting\r\n console.log('[OAuthFlow] ๐Ÿ”„ Starting localStorage polling interval (every 100ms)');\r\n \r\n const pollInterval = setInterval(() => {\r\n pollCount++;\r\n const stored = localStorage.getItem(storageKey);\r\n \r\n // Log every 1 second (10 * 100ms) for debugging - ALWAYS log to prove polling is running\r\n if (pollCount % 10 === 0) {\r\n console.log('[OAuthFlow] ๐Ÿ” Polling localStorage...', { \r\n key: storageKey.substring(0, 50) + '...',\r\n found: !!stored, \r\n pollCount,\r\n statePreview: state.substring(0, 20) + '...',\r\n intervalActive: true\r\n });\r\n \r\n // Re-check all keys every 10 seconds for debugging\r\n if (pollCount % 100 === 0) {\r\n immediateCheck();\r\n }\r\n }\r\n \r\n // ALWAYS check if we found the data (not just log every 10 polls)\r\n if (stored) {\r\n try {\r\n const data = JSON.parse(stored);\r\n \r\n // Log immediately when we find data (not just every 10 polls)\r\n if (pollCount === 1 || pollCount % 10 === 0) {\r\n console.log('[OAuthFlow] โœ… Found stored data!', { \r\n hasCode: !!data.code,\r\n hasState: !!data.state,\r\n stateMatch: data.state === state,\r\n storedState: data.state?.substring(0, 20) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n pollCount\r\n });\r\n }\r\n \r\n if (data.code && data.state === state) {\r\n const age = Date.now() - (data.timestamp || 0);\r\n if (age < 30000) { // 30 second timeout\r\n console.log('[OAuthFlow] โœ…โœ…โœ… Processing OAuth callback from localStorage!', { \r\n age: `${age}ms`, \r\n hasCode: !!data.code,\r\n codePreview: data.code.substring(0, 10) + '...',\r\n pollCount\r\n });\r\n // Found callback data, trigger storage event manually\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n // Note: broadcastChannel cleanup will happen in checkClosed interval\r\n storageListener(new StorageEvent('storage', {\r\n key: storageKey,\r\n newValue: stored,\r\n storageArea: localStorage,\r\n }));\r\n return; // Exit early to prevent further processing\r\n } else {\r\n console.warn('[OAuthFlow] โš ๏ธ Callback data too old, removing:', { age: `${age}ms` });\r\n localStorage.removeItem(storageKey);\r\n }\r\n } else {\r\n // Log state mismatch immediately when found\r\n console.warn('[OAuthFlow] โš ๏ธ State mismatch!', {\r\n storedState: data.state?.substring(0, 20) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n statesMatch: data.state === state,\r\n storedStateLength: data.state?.length,\r\n expectedStateLength: state.length,\r\n pollCount\r\n });\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] โŒ Error parsing localStorage callback:', error, { \r\n stored: stored?.substring(0, 100) + '...',\r\n pollCount \r\n });\r\n }\r\n } else {\r\n // Also check for ANY omenx_oauth_callback keys if we haven't found our specific key\r\n // This helps catch cases where the key format is slightly different\r\n // Check more frequently (every 5 polls = 500ms) to catch the callback quickly\r\n if (pollCount === 1 || pollCount % 5 === 0) {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n if (allKeys.length > 0) {\r\n console.log('[OAuthFlow] ๐Ÿ” Found localStorage keys (checking all for state match):', { \r\n count: allKeys.length,\r\n keys: allKeys.map(k => k.substring(0, 50) + '...'),\r\n lookingFor: storageKey.substring(0, 50) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n pollCount\r\n });\r\n \r\n // Check each key to see if any match our state (by value, not just key name)\r\n for (const key of allKeys) {\r\n const storedData = localStorage.getItem(key);\r\n if (storedData) {\r\n try {\r\n const data = JSON.parse(storedData);\r\n const statesMatch = data.state === state;\r\n console.log('[OAuthFlow] ๐Ÿ” Checking stored key:', {\r\n key: key.substring(0, 50) + '...',\r\n storedState: data.state?.substring(0, 20) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n statesMatch: statesMatch,\r\n storedStateLength: data.state?.length,\r\n expectedStateLength: state.length,\r\n hasCode: !!data.code,\r\n pollCount\r\n });\r\n \r\n // If state matches, process it even if the key name doesn't match exactly\r\n if (statesMatch && data.code) {\r\n const age = Date.now() - (data.timestamp || 0);\r\n if (age < 30000) {\r\n console.log('[OAuthFlow] โœ…โœ…โœ… Found matching state in different key! Processing...', {\r\n key: key.substring(0, 50) + '...',\r\n age: `${age}ms`,\r\n pollCount\r\n });\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n // Process the callback\r\n storageListener(new StorageEvent('storage', {\r\n key: key,\r\n newValue: storedData,\r\n storageArea: localStorage,\r\n }));\r\n return;\r\n }\r\n }\r\n } catch (e) {\r\n console.warn('[OAuthFlow] โš ๏ธ Error parsing key:', key, e);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }, 100); // Poll every 100ms\r\n \r\n // Also listen for BroadcastChannel as another fallback\r\n let broadcastChannel: BroadcastChannel | null = null;\r\n try {\r\n broadcastChannel = new BroadcastChannel('omenx_oauth');\r\n const broadcastListener = (event: MessageEvent) => {\r\n if (event.data?.type === 'OMENX_OAUTH_CODE' && event.data?.state === state) {\r\n console.log('[OAuthFlow] โœ… Received OAuth code via BroadcastChannel');\r\n messageReceived = true;\r\n clearInterval(pollInterval);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n \r\n const { code: codeFromBroadcast } = event.data;\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n this.exchangeCodeForToken(codeFromBroadcast, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n }\r\n };\r\n // BroadcastChannel uses onmessage, not addEventListener\r\n broadcastChannel.onmessage = broadcastListener;\r\n \r\n // Clean up will happen in checkClosed interval\r\n } catch (error) {\r\n console.warn('[OAuthFlow] BroadcastChannel not supported:', error);\r\n broadcastChannel = null;\r\n }\r\n \r\n // Log that we're starting to listen for OAuth callback\r\n console.log('[OAuthFlow] ๐Ÿ” Starting OAuth flow, listening for callback...', { \r\n state: state,\r\n statePreview: state.substring(0, 20) + '...',\r\n stateLength: state.length,\r\n hasOpener: !!window.opener,\r\n polling: true,\r\n broadcastChannel: true,\r\n expectedKey: `omenx_oauth_callback_${state}`\r\n });\r\n \r\n // Check if popup was closed\r\n // Only report cancellation if we haven't received a message yet\r\n let messageReceived = false;\r\n const originalMessageListener = messageListener;\r\n const wrappedMessageListener = async (event: MessageEvent) => {\r\n messageReceived = true;\r\n // Clean up listeners when message is received\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n await originalMessageListener(event);\r\n };\r\n window.removeEventListener('message', messageListener);\r\n window.addEventListener('message', wrappedMessageListener);\r\n \r\n /**\r\n * Check if popup is actually closed (not just on a different origin)\r\n * When a popup navigates to a different domain, popup.closed might be true\r\n * due to cross-origin restrictions, but the popup is still open.\r\n * We can detect this by trying to access popup.location - if it throws,\r\n * the popup is still open but on a different origin.\r\n */\r\n const isPopupActuallyClosed = (): boolean => {\r\n try {\r\n // If popup.closed is false, it's definitely still open\r\n if (!popup.closed) {\r\n return false;\r\n }\r\n \r\n // If popup.closed is true, we need to verify it's actually closed\r\n // by trying to access its location\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n const _ = popup.location.href;\r\n // If we can access location, popup is on same origin and closed\r\n return true;\r\n } catch (e) {\r\n // If accessing location throws, popup is on different origin (still open)\r\n // This is normal during OAuth flow when popup navigates to OAuth server\r\n return false;\r\n }\r\n } catch (e) {\r\n // If we can't check at all, assume popup is still open to be safe\r\n return false;\r\n }\r\n };\r\n \r\n // Track when popup appears closed - give grace period for callback to complete\r\n let popupClosedTime: number | null = null;\r\n const POPUP_CLOSED_GRACE_PERIOD = 5000; // 5 seconds grace period\r\n \r\n const checkClosed = setInterval(() => {\r\n // Skip check if we've already received a message\r\n if (messageReceived) {\r\n clearInterval(checkClosed);\r\n clearInterval(pollInterval);\r\n return;\r\n }\r\n \r\n // Check if popup is actually closed (handles cross-origin correctly)\r\n if (isPopupActuallyClosed()) {\r\n // First time we detect popup is closed - start grace period\r\n if (popupClosedTime === null) {\r\n popupClosedTime = Date.now();\r\n console.log('[OAuthFlow] โš ๏ธ Popup appears closed, starting grace period for callback...', {\r\n gracePeriod: `${POPUP_CLOSED_GRACE_PERIOD}ms`,\r\n pollCount,\r\n stillPolling: true\r\n });\r\n return; // Don't cancel yet - give callback time to complete\r\n }\r\n \r\n // Check if grace period has expired\r\n const timeSinceClosed = Date.now() - popupClosedTime;\r\n if (timeSinceClosed < POPUP_CLOSED_GRACE_PERIOD) {\r\n // Still in grace period - keep polling\r\n console.log('[OAuthFlow] โณ Popup closed, but still in grace period...', {\r\n timeRemaining: `${POPUP_CLOSED_GRACE_PERIOD - timeSinceClosed}ms`,\r\n pollCount\r\n });\r\n return;\r\n }\r\n \r\n // Grace period expired - popup is truly closed without callback\r\n console.log('[OAuthFlow] โŒ Popup closed and grace period expired without callback', {\r\n timeSinceClosed: `${timeSinceClosed}ms`,\r\n pollCount,\r\n finalCheck: 'Checking localStorage one last time...'\r\n });\r\n \r\n // Final check of localStorage before giving up\r\n immediateCheck();\r\n \r\n clearInterval(checkClosed);\r\n clearInterval(pollInterval);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n \r\n // Only report cancellation if we haven't received a message\r\n if (!messageReceived) {\r\n const error = new Error('Authentication was cancelled.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n }\r\n } else {\r\n // Popup is still open - reset closed time\r\n if (popupClosedTime !== null) {\r\n console.log('[OAuthFlow] โœ… Popup is open again (was temporarily on different origin)');\r\n popupClosedTime = null;\r\n }\r\n }\r\n }, 1000);\r\n });\r\n }\r\n\r\n /**\r\n * Exchange authorization code for access token\r\n */\r\n private async exchangeCodeForToken(\r\n code: string,\r\n redirectUri: string,\r\n codeVerifier?: string\r\n ): Promise<OAuthTokenResponse> {\r\n const body: any = {\r\n code,\r\n redirect_uri: redirectUri,\r\n grant_type: 'authorization_code',\r\n };\r\n\r\n if (codeVerifier) {\r\n body.code_verifier = codeVerifier;\r\n }\r\n\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n // Note: API key should be included via Authorization header\r\n // This should be set by the game's backend, not the SDK\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({ message: 'Failed to exchange code for token' }));\r\n throw new Error(error.message || 'Failed to exchange code for token');\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Generate random state for CSRF protection\r\n */\r\n private generateState(): string {\r\n const array = new Uint8Array(32);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\ninterface IframeAuthConfig {\r\n gameId: string;\r\n parentOrigin?: string;\r\n onAuth: (authData: AuthData) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles authentication data passed from parent window via postMessage\r\n */\r\nexport class IframeAuth {\r\n private config: IframeAuthConfig;\r\n private messageListener: ((event: MessageEvent) => void) | null = null;\r\n\r\n constructor(config: IframeAuthConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Initialize iframe authentication listener\r\n */\r\n init(): void {\r\n // Request auth data from parent\r\n this.requestAuth();\r\n\r\n // Listen for auth data from parent\r\n this.messageListener = (event: MessageEvent) => {\r\n // Validate origin if specified\r\n if (this.config.parentOrigin) {\r\n try {\r\n const parentUrl = new URL(this.config.parentOrigin);\r\n if (event.origin !== parentUrl.origin) {\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse parent origin, skip validation (development)\r\n }\r\n }\r\n\r\n // Handle auth data\r\n if (event.data?.type === 'OMENX_AUTH') {\r\n const authData = event.data.payload as AuthData;\r\n\r\n // Validate game ID\r\n if (authData.gameId !== this.config.gameId) {\r\n this.config.onError?.(new Error(`Game ID mismatch. Expected ${this.config.gameId}, got ${authData.gameId}`));\r\n return;\r\n }\r\n\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onError?.(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n this.config.onAuth(authData);\r\n }\r\n };\r\n\r\n window.addEventListener('message', this.messageListener);\r\n }\r\n\r\n /**\r\n * Request authentication data from parent window\r\n */\r\n private requestAuth(): void {\r\n if (window.parent === window) {\r\n // Not in an iframe\r\n return;\r\n }\r\n\r\n // Send request to parent\r\n const parentOrigin = this.config.parentOrigin || '*';\r\n window.parent.postMessage(\r\n {\r\n type: 'OMENX_AUTH_REQUEST',\r\n gameId: this.config.gameId,\r\n },\r\n parentOrigin\r\n );\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy(): void {\r\n if (this.messageListener) {\r\n window.removeEventListener('message', this.messageListener);\r\n this.messageListener = null;\r\n }\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\n/**\r\n * Manages token storage and retrieval\r\n */\r\nexport class TokenManager {\r\n private storageKeyPrefix: string;\r\n\r\n constructor(storageKeyPrefix: string = 'omenx_game_') {\r\n this.storageKeyPrefix = storageKeyPrefix;\r\n }\r\n\r\n /**\r\n * Store authentication data\r\n */\r\n storeAuth(authData: AuthData, refreshToken: string, expiresIn: number): void {\r\n try {\r\n localStorage.setItem(`${this.storageKeyPrefix}auth`, JSON.stringify(authData));\r\n localStorage.setItem(`${this.storageKeyPrefix}refresh_token`, refreshToken);\r\n localStorage.setItem(`${this.storageKeyPrefix}expires_at`, String(Date.now() + (expiresIn * 1000)));\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to store auth data:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Get stored authentication data\r\n */\r\n getStoredAuth(): AuthData | null {\r\n try {\r\n const stored = localStorage.getItem(`${this.storageKeyPrefix}auth`);\r\n if (!stored) {\r\n return null;\r\n }\r\n return JSON.parse(stored) as AuthData;\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve auth data:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get stored refresh token\r\n */\r\n getRefreshToken(): string | null {\r\n try {\r\n return localStorage.getItem(`${this.storageKeyPrefix}refresh_token`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve refresh token:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Clear all stored authentication data\r\n */\r\n clearStorage(): void {\r\n try {\r\n localStorage.removeItem(`${this.storageKeyPrefix}auth`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}refresh_token`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}expires_at`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to clear storage:', error);\r\n }\r\n }\r\n}\r\n","import type {\r\n OmenXGameSDKConfig,\r\n AuthData,\r\n OAuthOptions,\r\n OAuthTokenResponse,\r\n ApiCallOptions,\r\n} from './types';\r\nimport { OAuthFlow } from './oauth';\r\nimport { IframeAuth } from './iframe-auth';\r\nimport { TokenManager } from './token-manager';\r\n\r\n/**\r\n * OmenX Game SDK\r\n * \r\n * Provides authentication and API integration for games on the OmenX platform.\r\n * Supports both OAuth-style authentication and iframe authentication passing.\r\n */\r\nexport class OmenXGameSDK {\r\n private config: Required<OmenXGameSDKConfig>;\r\n private oauthFlow: OAuthFlow;\r\n private iframeAuth: IframeAuth | null = null;\r\n private tokenManager: TokenManager;\r\n private currentAuthData: AuthData | null = null;\r\n\r\n constructor(config: OmenXGameSDKConfig) {\r\n // Set defaults\r\n const apiBaseUrl = config.apiBaseUrl || 'https://api.omen.foundation';\r\n this.config = {\r\n gameId: config.gameId,\r\n apiBaseUrl: apiBaseUrl,\r\n oauthAuthorizeUrl: config.oauthAuthorizeUrl || `${apiBaseUrl}/v1/oauth/authorize`,\r\n oauthTokenUrl: config.oauthTokenUrl || `${apiBaseUrl}/v1/oauth/token`,\r\n onAuth: config.onAuth || (() => {}),\r\n onAuthError: config.onAuthError || ((error) => console.error('[OmenX SDK] Auth error:', error)),\r\n onLogout: config.onLogout || (() => {}),\r\n enableIframeAuth: config.enableIframeAuth !== false,\r\n parentOrigin: config.parentOrigin ?? '',\r\n storageKeyPrefix: config.storageKeyPrefix || 'omenx_game_',\r\n };\r\n\r\n // Initialize components\r\n this.tokenManager = new TokenManager(this.config.storageKeyPrefix);\r\n this.oauthFlow = new OAuthFlow({\r\n gameId: this.config.gameId,\r\n oauthAuthorizeUrl: this.config.oauthAuthorizeUrl,\r\n oauthTokenUrl: this.config.oauthTokenUrl,\r\n apiBaseUrl: this.config.apiBaseUrl,\r\n onTokenReceived: this.handleTokenReceived.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n\r\n if (this.config.enableIframeAuth) {\r\n this.iframeAuth = new IframeAuth({\r\n gameId: this.config.gameId,\r\n parentOrigin: this.config.parentOrigin || undefined,\r\n onAuth: this.handleAuthData.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Initialize the SDK\r\n * Call this after creating an instance\r\n */\r\n async init(): Promise<void> {\r\n // Try to restore from stored token\r\n const storedAuth = this.tokenManager.getStoredAuth();\r\n if (storedAuth) {\r\n // Check if token is still valid (not expired)\r\n const expiresAt = storedAuth.timestamp + (3600 * 1000); // 1 hour default\r\n if (Date.now() < expiresAt) {\r\n this.currentAuthData = storedAuth;\r\n this.config.onAuth(storedAuth);\r\n return;\r\n } else {\r\n // Token expired, try to refresh\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n return;\r\n } catch (error) {\r\n // Refresh failed, clear storage\r\n this.tokenManager.clearStorage();\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If iframe auth is enabled, try to get auth from parent\r\n if (this.config.enableIframeAuth && this.iframeAuth !== null) {\r\n this.iframeAuth.init();\r\n }\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<AuthData> {\r\n return this.oauthFlow.authenticate(options);\r\n }\r\n\r\n /**\r\n * Get current authentication data\r\n */\r\n getAuthData(): AuthData | null {\r\n return this.currentAuthData;\r\n }\r\n\r\n /**\r\n * Check if user is authenticated\r\n */\r\n isAuthenticated(): boolean {\r\n return this.currentAuthData !== null;\r\n }\r\n\r\n /**\r\n * Logout user\r\n */\r\n async logout(): Promise<void> {\r\n // Revoke token if we have one\r\n if (this.currentAuthData?.accessToken) {\r\n try {\r\n await this.apiCall('/v1/oauth/revoke', {\r\n method: 'POST',\r\n body: { token: this.currentAuthData.accessToken },\r\n includeAuth: false, // Don't include auth header for revoke\r\n });\r\n } catch (error) {\r\n // Ignore errors on revoke\r\n console.warn('[OmenX SDK] Failed to revoke token:', error);\r\n }\r\n }\r\n\r\n // Clear local state\r\n this.currentAuthData = null;\r\n this.tokenManager.clearStorage();\r\n this.config.onLogout();\r\n }\r\n\r\n /**\r\n * Make an authenticated API call\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...options.headers,\r\n };\r\n\r\n // Add authentication header if needed\r\n if (options.includeAuth !== false && this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n }\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n // If unauthorized, try to refresh token\r\n if (response.status === 401 && this.currentAuthData) {\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n // Retry the request with new token\r\n if (this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n return fetch(url, { ...fetchOptions, headers });\r\n }\r\n } catch (error) {\r\n // Refresh failed, logout\r\n await this.logout();\r\n throw new Error('Authentication expired. Please login again.');\r\n }\r\n }\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Handle token received from OAuth flow\r\n */\r\n private async handleTokenReceived(tokenResponse: OAuthTokenResponse): Promise<void> {\r\n const authData: AuthData = {\r\n accessToken: tokenResponse.access_token,\r\n walletAddress: tokenResponse.user.walletAddress,\r\n userId: tokenResponse.user.userId,\r\n profileName: tokenResponse.user.profileName,\r\n profilePicture: tokenResponse.user.profilePicture,\r\n email: tokenResponse.user.email,\r\n gameId: this.config.gameId,\r\n timestamp: Date.now(),\r\n };\r\n\r\n // Store tokens\r\n this.tokenManager.storeAuth(authData, tokenResponse.refresh_token, tokenResponse.expires_in);\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Handle auth data from iframe\r\n */\r\n private handleAuthData(authData: AuthData): void {\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onAuthError(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Refresh access token using refresh token\r\n */\r\n private async refreshAccessToken(refreshToken: string): Promise<void> {\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n grant_type: 'refresh_token',\r\n refresh_token: refreshToken,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error('Failed to refresh token');\r\n }\r\n\r\n const tokenResponse: OAuthTokenResponse = await response.json();\r\n await this.handleTokenReceived(tokenResponse);\r\n }\r\n}\r\n","import type { ApiCallOptions } from './types';\r\n\r\ninterface ServerSDKConfig {\r\n /**\r\n * Your developer API key (from developer portal)\r\n */\r\n apiKey: string;\r\n\r\n /**\r\n * OmenX API base URL (default: https://api.omen.foundation)\r\n */\r\n apiBaseUrl?: string;\r\n}\r\n\r\n/**\r\n * OmenX Game SDK - Server Mode\r\n * \r\n * For Node.js backends using developer API keys.\r\n * This mode allows server-to-server communication with the OmenX API.\r\n */\r\nexport class OmenXServerSDK {\r\n private config: Required<ServerSDKConfig>;\r\n private apiKey: string;\r\n\r\n constructor(config: ServerSDKConfig) {\r\n this.apiKey = config.apiKey;\r\n this.config = {\r\n apiKey: config.apiKey,\r\n apiBaseUrl: config.apiBaseUrl || 'https://api.omen.foundation',\r\n };\r\n }\r\n\r\n /**\r\n * Make an authenticated API call using the developer API key\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.apiKey}`,\r\n ...options.headers,\r\n };\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => 'Unknown error');\r\n throw new Error(`API call failed: ${response.status} ${response.statusText} - ${errorText}`);\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Health check\r\n */\r\n async healthCheck(): Promise<any> {\r\n const response = await this.apiCall('/v1/health', { includeAuth: false });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get API key information\r\n */\r\n async getApiKeyInfo(): Promise<any> {\r\n const response = await this.apiCall('/v1/auth/me');\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Player Operations\r\n */\r\n\r\n /**\r\n * Get native and ERC20 token balances for a wallet\r\n */\r\n async getPlayerBalances(wallet: string, chainId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/players/${wallet}/balances?chainId=${chainId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get paginated NFTs for a wallet\r\n */\r\n async getPlayerNfts(\r\n wallet: string,\r\n chainId: string,\r\n options?: {\r\n contract?: string;\r\n cursor?: string;\r\n limit?: number;\r\n }\r\n ): Promise<any> {\r\n const params = new URLSearchParams({ chainId });\r\n if (options?.contract) params.append('contract', options.contract);\r\n if (options?.cursor) params.append('cursor', options.cursor);\r\n if (options?.limit) params.append('limit', options.limit.toString());\r\n \r\n const response = await this.apiCall(`/v1/players/${wallet}/nfts?${params.toString()}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Purchase Operations\r\n */\r\n\r\n /**\r\n * Create a server-authoritative purchase\r\n */\r\n async createPurchase(params: {\r\n playerWallet?: string;\r\n walletAddress?: string; // Legacy field name\r\n skuId?: string;\r\n sku?: string; // Legacy field name\r\n quantity?: number;\r\n idempotencyKey?: string;\r\n paymentMethod?: string;\r\n metadata?: Record<string, any>;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/purchases', {\r\n method: 'POST',\r\n body: params,\r\n headers: params.idempotencyKey ? {\r\n 'Idempotency-Key': params.idempotencyKey,\r\n } : undefined,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * NFT Template Operations\r\n */\r\n\r\n /**\r\n * Get all NFT templates for a game\r\n */\r\n async getNftTemplates(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/templates?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get NFT contract address for a game\r\n */\r\n async getNftContract(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/contract?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Mint NFTs (single or batch)\r\n */\r\n async mintNfts(params: {\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch mint NFTs\r\n */\r\n async batchMintNfts(mints: Array<{\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }>): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint/batch', {\r\n method: 'POST',\r\n body: { mints },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Update NFT metadata\r\n */\r\n async updateNftMetadata(\r\n tokenId: string,\r\n metadata: {\r\n attributes?: Record<string, string | number | boolean>;\r\n name?: string;\r\n description?: string;\r\n imageUrl?: string;\r\n }\r\n ): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}/metadata`, {\r\n method: 'PUT',\r\n body: metadata,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Burn NFT (single)\r\n */\r\n async burnNft(tokenId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}`, {\r\n method: 'DELETE',\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch burn NFTs\r\n */\r\n async batchBurnNfts(tokenIds: string[]): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/burn/batch', {\r\n method: 'POST',\r\n body: { tokenIds },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Pack opener - mint random NFTs from a drop table\r\n */\r\n async packOpener(params: {\r\n dropTableId: string;\r\n recipientAddress: string;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/pack-opener', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n}\r\n"]}
package/dist/index.mjs CHANGED
@@ -184,6 +184,7 @@ var OAuthFlow = class {
184
184
  }
185
185
  };
186
186
  immediateCheck();
187
+ console.log("[OAuthFlow] \u{1F504} Starting localStorage polling interval (every 100ms)");
187
188
  const pollInterval = setInterval(() => {
188
189
  pollCount++;
189
190
  const stored = localStorage.getItem(storageKey);
@@ -192,7 +193,8 @@ var OAuthFlow = class {
192
193
  key: storageKey.substring(0, 50) + "...",
193
194
  found: !!stored,
194
195
  pollCount,
195
- statePreview: state.substring(0, 20) + "..."
196
+ statePreview: state.substring(0, 20) + "...",
197
+ intervalActive: true
196
198
  });
197
199
  if (pollCount % 100 === 0) {
198
200
  immediateCheck();
@@ -371,11 +373,38 @@ var OAuthFlow = class {
371
373
  return false;
372
374
  }
373
375
  };
376
+ let popupClosedTime = null;
377
+ const POPUP_CLOSED_GRACE_PERIOD = 5e3;
374
378
  const checkClosed = setInterval(() => {
375
379
  if (messageReceived) {
380
+ clearInterval(checkClosed);
381
+ clearInterval(pollInterval);
376
382
  return;
377
383
  }
378
384
  if (isPopupActuallyClosed()) {
385
+ if (popupClosedTime === null) {
386
+ popupClosedTime = Date.now();
387
+ console.log("[OAuthFlow] \u26A0\uFE0F Popup appears closed, starting grace period for callback...", {
388
+ gracePeriod: `${POPUP_CLOSED_GRACE_PERIOD}ms`,
389
+ pollCount,
390
+ stillPolling: true
391
+ });
392
+ return;
393
+ }
394
+ const timeSinceClosed = Date.now() - popupClosedTime;
395
+ if (timeSinceClosed < POPUP_CLOSED_GRACE_PERIOD) {
396
+ console.log("[OAuthFlow] \u23F3 Popup closed, but still in grace period...", {
397
+ timeRemaining: `${POPUP_CLOSED_GRACE_PERIOD - timeSinceClosed}ms`,
398
+ pollCount
399
+ });
400
+ return;
401
+ }
402
+ console.log("[OAuthFlow] \u274C Popup closed and grace period expired without callback", {
403
+ timeSinceClosed: `${timeSinceClosed}ms`,
404
+ pollCount,
405
+ finalCheck: "Checking localStorage one last time..."
406
+ });
407
+ immediateCheck();
379
408
  clearInterval(checkClosed);
380
409
  clearInterval(pollInterval);
381
410
  window.removeEventListener("message", wrappedMessageListener);
@@ -389,6 +418,11 @@ var OAuthFlow = class {
389
418
  this.config.onError?.(error);
390
419
  reject(error);
391
420
  }
421
+ } else {
422
+ if (popupClosedTime !== null) {
423
+ console.log("[OAuthFlow] \u2705 Popup is open again (was temporarily on different origin)");
424
+ popupClosedTime = null;
425
+ }
392
426
  }
393
427
  }, 1e3);
394
428
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/pkce.ts","../src/oauth.ts","../src/iframe-auth.ts","../src/token-manager.ts","../src/sdk.ts","../src/server-sdk.ts"],"names":["codeVerifier"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * Generate PKCE (Proof Key for Code Exchange) code challenge and verifier\r\n */\r\nexport async function generatePKCE(): Promise<{ codeVerifier: string; codeChallenge: string }> {\r\n // Generate code verifier (43-128 characters, URL-safe)\r\n const codeVerifier = generateRandomString(128);\r\n\r\n // Generate code challenge (SHA256 hash of code verifier, base64url encoded)\r\n const hash = await sha256(codeVerifier);\r\n const codeChallenge = base64URLEncode(hash);\r\n\r\n return { codeVerifier, codeChallenge };\r\n}\r\n\r\n/**\r\n * Generate random URL-safe string\r\n */\r\nfunction generateRandomString(length: number): string {\r\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\r\n const array = new Uint8Array(length);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => charset[byte % charset.length]).join('');\r\n}\r\n\r\n/**\r\n * Base64 URL encode (without padding)\r\n */\r\nfunction base64URLEncode(buffer: ArrayBuffer): string {\r\n const base64 = btoa(String.fromCharCode(...new Uint8Array(buffer)));\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\r\n}\r\n\r\n/**\r\n * SHA256 hash\r\n */\r\nasync function sha256(message: string): Promise<ArrayBuffer> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(message);\r\n return crypto.subtle.digest('SHA-256', data);\r\n}\r\n","import type { OAuthOptions, OAuthTokenResponse } from './types';\r\nimport { generatePKCE } from './pkce';\r\n\r\ninterface OAuthFlowConfig {\r\n gameId: string;\r\n oauthAuthorizeUrl: string;\r\n oauthTokenUrl: string;\r\n apiBaseUrl: string;\r\n onTokenReceived: (tokenResponse: OAuthTokenResponse) => Promise<void>;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles OAuth 2.0 Authorization Code Grant flow with PKCE\r\n */\r\nexport class OAuthFlow {\r\n private config: OAuthFlowConfig;\r\n\r\n constructor(config: OAuthFlowConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<any> {\r\n // Generate state for CSRF protection\r\n const state = options.state || this.generateState();\r\n \r\n // CRITICAL: Clean up old OAuth callback entries from localStorage\r\n // This prevents state mismatches when starting a new flow\r\n try {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n console.log('[OAuthFlow] ๐Ÿงน Cleaning up old OAuth entries:', { count: allKeys.length });\r\n allKeys.forEach(key => {\r\n try {\r\n const data = localStorage.getItem(key);\r\n if (data) {\r\n const parsed = JSON.parse(data);\r\n const age = Date.now() - (parsed.timestamp || 0);\r\n // Remove entries older than 5 minutes\r\n if (age > 300000) {\r\n localStorage.removeItem(key);\r\n console.log('[OAuthFlow] ๐Ÿ—‘๏ธ Removed old entry:', key.substring(0, 50) + '...', { age: `${age}ms` });\r\n }\r\n }\r\n } catch (e) {\r\n // If we can't parse it, remove it anyway\r\n localStorage.removeItem(key);\r\n }\r\n });\r\n } catch (error) {\r\n console.warn('[OAuthFlow] โš ๏ธ Error cleaning up old entries:', error);\r\n }\r\n \r\n // Generate PKCE if enabled\r\n let codeChallenge: string | undefined;\r\n let codeVerifier: string | undefined;\r\n if (options.enablePKCE !== false) {\r\n const pkce = await generatePKCE();\r\n codeChallenge = pkce.codeChallenge;\r\n codeVerifier = pkce.codeVerifier;\r\n // Store code verifier for later use\r\n sessionStorage.setItem(`omenx_pkce_${state}`, codeVerifier);\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n // Build authorization URL\r\n const params = new URLSearchParams({\r\n client_id: this.config.gameId,\r\n redirect_uri: options.redirectUri,\r\n response_type: 'code',\r\n state: state,\r\n });\r\n\r\n if (codeChallenge) {\r\n params.append('code_challenge', codeChallenge);\r\n params.append('code_challenge_method', 'S256');\r\n }\r\n\r\n const authUrl = `${this.config.oauthAuthorizeUrl}?${params.toString()}`;\r\n\r\n // Open popup window\r\n const popup = window.open(\r\n authUrl,\r\n 'OmenX Authentication',\r\n 'width=500,height=600,left=' + (window.screen.width / 2 - 250) + ',top=' + (window.screen.height / 2 - 300)\r\n );\r\n\r\n if (!popup) {\r\n const error = new Error('Failed to open popup window. Please allow popups for this site.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Listen for authorization code\r\n const messageListener = async (event: MessageEvent) => {\r\n // Validate origin - the callback page is on the game's domain, not the OAuth server\r\n // We should check that the message comes from the same origin as the current window\r\n // (the game's domain where the callback page is hosted)\r\n try {\r\n // The callback page is on the game's domain, so check against current origin\r\n const currentOrigin = window.location.origin;\r\n if (event.origin !== currentOrigin) {\r\n // Message not from our domain - ignore it\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse the URL, skip origin check (development)\r\n }\r\n\r\n if (event.data?.type === 'OMENX_OAUTH_CODE') {\r\n window.removeEventListener('message', messageListener);\r\n popup.close();\r\n\r\n const { code, state: returnedState } = event.data;\r\n\r\n // Validate state\r\n if (returnedState !== state) {\r\n const error = new Error('Invalid state parameter. Possible CSRF attack.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n\r\n try {\r\n // Exchange code for token\r\n const tokenResponse = await this.exchangeCodeForToken(code, options.redirectUri, codeVerifier);\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n } catch (error) {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n }\r\n }\r\n };\r\n\r\n window.addEventListener('message', messageListener);\r\n\r\n // Also listen for localStorage events as fallback (in case window.opener is lost)\r\n // The callback page will store the code in localStorage if postMessage fails\r\n const storageListener = (event: StorageEvent) => {\r\n if (!event.key || !event.key.startsWith('omenx_oauth_callback_')) {\r\n return;\r\n }\r\n \r\n const callbackState = event.key.replace('omenx_oauth_callback_', '');\r\n if (callbackState !== state) {\r\n return; // Not our callback\r\n }\r\n \r\n try {\r\n const data = JSON.parse(event.newValue || '{}');\r\n if (data.code && data.state === state) {\r\n console.log('[OAuthFlow] Received OAuth code via localStorage fallback');\r\n messageReceived = true;\r\n window.removeEventListener('storage', storageListener);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n \r\n // Process the code the same way as postMessage\r\n const { code: codeFromStorage } = data;\r\n \r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n // Exchange code for token\r\n this.exchangeCodeForToken(codeFromStorage, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n \r\n // Clean up localStorage\r\n localStorage.removeItem(event.key!);\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] Error processing localStorage callback:', error);\r\n }\r\n };\r\n \r\n window.addEventListener('storage', storageListener);\r\n \r\n // Also poll localStorage as additional fallback (storage events don't fire in same window)\r\n // This is critical because when the popup closes, storage events might not fire\r\n let pollCount = 0;\r\n const storageKey = `omenx_oauth_callback_${state}`;\r\n \r\n // Immediately check localStorage on first poll (before interval starts)\r\n // This helps catch callback data that was stored before polling started\r\n const immediateCheck = () => {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n console.log('[OAuthFlow] ๐Ÿ” Immediate localStorage check:', { \r\n count: allKeys.length,\r\n keys: allKeys.map(k => k.substring(0, 50) + '...'),\r\n lookingFor: storageKey.substring(0, 50) + '...',\r\n expectedState: state.substring(0, 20) + '...'\r\n });\r\n \r\n // Try to find a match by checking each key\r\n for (const key of allKeys) {\r\n const storedData = localStorage.getItem(key);\r\n if (storedData) {\r\n try {\r\n const data = JSON.parse(storedData);\r\n console.log('[OAuthFlow] ๐Ÿ” Checking stored key:', {\r\n key: key.substring(0, 50) + '...',\r\n storedState: data.state?.substring(0, 20) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n statesMatch: data.state === state,\r\n hasCode: !!data.code,\r\n timestamp: data.timestamp,\r\n age: data.timestamp ? `${Date.now() - data.timestamp}ms` : 'unknown'\r\n });\r\n } catch (e) {\r\n console.warn('[OAuthFlow] โš ๏ธ Error parsing stored key:', key, e);\r\n }\r\n }\r\n }\r\n };\r\n \r\n // Run immediate check\r\n immediateCheck();\r\n \r\n const pollInterval = setInterval(() => {\r\n pollCount++;\r\n const stored = localStorage.getItem(storageKey);\r\n \r\n // Log every 1 second (10 * 100ms) for debugging\r\n if (pollCount % 10 === 0) {\r\n console.log('[OAuthFlow] ๐Ÿ” Polling localStorage...', { \r\n key: storageKey.substring(0, 50) + '...',\r\n found: !!stored, \r\n pollCount,\r\n statePreview: state.substring(0, 20) + '...'\r\n });\r\n \r\n // Re-check all keys every 10 seconds for debugging\r\n if (pollCount % 100 === 0) {\r\n immediateCheck();\r\n }\r\n }\r\n \r\n // ALWAYS check if we found the data (not just log every 10 polls)\r\n if (stored) {\r\n try {\r\n const data = JSON.parse(stored);\r\n \r\n // Log immediately when we find data (not just every 10 polls)\r\n if (pollCount === 1 || pollCount % 10 === 0) {\r\n console.log('[OAuthFlow] โœ… Found stored data!', { \r\n hasCode: !!data.code,\r\n hasState: !!data.state,\r\n stateMatch: data.state === state,\r\n storedState: data.state?.substring(0, 20) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n pollCount\r\n });\r\n }\r\n \r\n if (data.code && data.state === state) {\r\n const age = Date.now() - (data.timestamp || 0);\r\n if (age < 30000) { // 30 second timeout\r\n console.log('[OAuthFlow] โœ…โœ…โœ… Processing OAuth callback from localStorage!', { \r\n age: `${age}ms`, \r\n hasCode: !!data.code,\r\n codePreview: data.code.substring(0, 10) + '...',\r\n pollCount\r\n });\r\n // Found callback data, trigger storage event manually\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n // Note: broadcastChannel cleanup will happen in checkClosed interval\r\n storageListener(new StorageEvent('storage', {\r\n key: storageKey,\r\n newValue: stored,\r\n storageArea: localStorage,\r\n }));\r\n return; // Exit early to prevent further processing\r\n } else {\r\n console.warn('[OAuthFlow] โš ๏ธ Callback data too old, removing:', { age: `${age}ms` });\r\n localStorage.removeItem(storageKey);\r\n }\r\n } else {\r\n // Log state mismatch immediately when found\r\n console.warn('[OAuthFlow] โš ๏ธ State mismatch!', {\r\n storedState: data.state?.substring(0, 20) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n statesMatch: data.state === state,\r\n storedStateLength: data.state?.length,\r\n expectedStateLength: state.length,\r\n pollCount\r\n });\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] โŒ Error parsing localStorage callback:', error, { \r\n stored: stored?.substring(0, 100) + '...',\r\n pollCount \r\n });\r\n }\r\n } else {\r\n // Also check for ANY omenx_oauth_callback keys if we haven't found our specific key\r\n // This helps catch cases where the key format is slightly different\r\n // Check more frequently (every 5 polls = 500ms) to catch the callback quickly\r\n if (pollCount === 1 || pollCount % 5 === 0) {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n if (allKeys.length > 0) {\r\n console.log('[OAuthFlow] ๐Ÿ” Found localStorage keys (checking all for state match):', { \r\n count: allKeys.length,\r\n keys: allKeys.map(k => k.substring(0, 50) + '...'),\r\n lookingFor: storageKey.substring(0, 50) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n pollCount\r\n });\r\n \r\n // Check each key to see if any match our state (by value, not just key name)\r\n for (const key of allKeys) {\r\n const storedData = localStorage.getItem(key);\r\n if (storedData) {\r\n try {\r\n const data = JSON.parse(storedData);\r\n const statesMatch = data.state === state;\r\n console.log('[OAuthFlow] ๐Ÿ” Checking stored key:', {\r\n key: key.substring(0, 50) + '...',\r\n storedState: data.state?.substring(0, 20) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n statesMatch: statesMatch,\r\n storedStateLength: data.state?.length,\r\n expectedStateLength: state.length,\r\n hasCode: !!data.code,\r\n pollCount\r\n });\r\n \r\n // If state matches, process it even if the key name doesn't match exactly\r\n if (statesMatch && data.code) {\r\n const age = Date.now() - (data.timestamp || 0);\r\n if (age < 30000) {\r\n console.log('[OAuthFlow] โœ…โœ…โœ… Found matching state in different key! Processing...', {\r\n key: key.substring(0, 50) + '...',\r\n age: `${age}ms`,\r\n pollCount\r\n });\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n // Process the callback\r\n storageListener(new StorageEvent('storage', {\r\n key: key,\r\n newValue: storedData,\r\n storageArea: localStorage,\r\n }));\r\n return;\r\n }\r\n }\r\n } catch (e) {\r\n console.warn('[OAuthFlow] โš ๏ธ Error parsing key:', key, e);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }, 100); // Poll every 100ms\r\n \r\n // Also listen for BroadcastChannel as another fallback\r\n let broadcastChannel: BroadcastChannel | null = null;\r\n try {\r\n broadcastChannel = new BroadcastChannel('omenx_oauth');\r\n const broadcastListener = (event: MessageEvent) => {\r\n if (event.data?.type === 'OMENX_OAUTH_CODE' && event.data?.state === state) {\r\n console.log('[OAuthFlow] โœ… Received OAuth code via BroadcastChannel');\r\n messageReceived = true;\r\n clearInterval(pollInterval);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n \r\n const { code: codeFromBroadcast } = event.data;\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n this.exchangeCodeForToken(codeFromBroadcast, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n }\r\n };\r\n // BroadcastChannel uses onmessage, not addEventListener\r\n broadcastChannel.onmessage = broadcastListener;\r\n \r\n // Clean up will happen in checkClosed interval\r\n } catch (error) {\r\n console.warn('[OAuthFlow] BroadcastChannel not supported:', error);\r\n broadcastChannel = null;\r\n }\r\n \r\n // Log that we're starting to listen for OAuth callback\r\n console.log('[OAuthFlow] ๐Ÿ” Starting OAuth flow, listening for callback...', { \r\n state: state,\r\n statePreview: state.substring(0, 20) + '...',\r\n stateLength: state.length,\r\n hasOpener: !!window.opener,\r\n polling: true,\r\n broadcastChannel: true,\r\n expectedKey: `omenx_oauth_callback_${state}`\r\n });\r\n \r\n // Check if popup was closed\r\n // Only report cancellation if we haven't received a message yet\r\n let messageReceived = false;\r\n const originalMessageListener = messageListener;\r\n const wrappedMessageListener = async (event: MessageEvent) => {\r\n messageReceived = true;\r\n // Clean up listeners when message is received\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n await originalMessageListener(event);\r\n };\r\n window.removeEventListener('message', messageListener);\r\n window.addEventListener('message', wrappedMessageListener);\r\n \r\n /**\r\n * Check if popup is actually closed (not just on a different origin)\r\n * When a popup navigates to a different domain, popup.closed might be true\r\n * due to cross-origin restrictions, but the popup is still open.\r\n * We can detect this by trying to access popup.location - if it throws,\r\n * the popup is still open but on a different origin.\r\n */\r\n const isPopupActuallyClosed = (): boolean => {\r\n try {\r\n // If popup.closed is false, it's definitely still open\r\n if (!popup.closed) {\r\n return false;\r\n }\r\n \r\n // If popup.closed is true, we need to verify it's actually closed\r\n // by trying to access its location\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n const _ = popup.location.href;\r\n // If we can access location, popup is on same origin and closed\r\n return true;\r\n } catch (e) {\r\n // If accessing location throws, popup is on different origin (still open)\r\n // This is normal during OAuth flow when popup navigates to OAuth server\r\n return false;\r\n }\r\n } catch (e) {\r\n // If we can't check at all, assume popup is still open to be safe\r\n return false;\r\n }\r\n };\r\n \r\n const checkClosed = setInterval(() => {\r\n // Skip check if we've already received a message\r\n if (messageReceived) {\r\n return;\r\n }\r\n \r\n // Check if popup is actually closed (handles cross-origin correctly)\r\n if (isPopupActuallyClosed()) {\r\n clearInterval(checkClosed);\r\n clearInterval(pollInterval);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n // Only report cancellation if we haven't received a message\r\n if (!messageReceived) {\r\n const error = new Error('Authentication was cancelled.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n }\r\n }\r\n }, 1000);\r\n });\r\n }\r\n\r\n /**\r\n * Exchange authorization code for access token\r\n */\r\n private async exchangeCodeForToken(\r\n code: string,\r\n redirectUri: string,\r\n codeVerifier?: string\r\n ): Promise<OAuthTokenResponse> {\r\n const body: any = {\r\n code,\r\n redirect_uri: redirectUri,\r\n grant_type: 'authorization_code',\r\n };\r\n\r\n if (codeVerifier) {\r\n body.code_verifier = codeVerifier;\r\n }\r\n\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n // Note: API key should be included via Authorization header\r\n // This should be set by the game's backend, not the SDK\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({ message: 'Failed to exchange code for token' }));\r\n throw new Error(error.message || 'Failed to exchange code for token');\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Generate random state for CSRF protection\r\n */\r\n private generateState(): string {\r\n const array = new Uint8Array(32);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\ninterface IframeAuthConfig {\r\n gameId: string;\r\n parentOrigin?: string;\r\n onAuth: (authData: AuthData) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles authentication data passed from parent window via postMessage\r\n */\r\nexport class IframeAuth {\r\n private config: IframeAuthConfig;\r\n private messageListener: ((event: MessageEvent) => void) | null = null;\r\n\r\n constructor(config: IframeAuthConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Initialize iframe authentication listener\r\n */\r\n init(): void {\r\n // Request auth data from parent\r\n this.requestAuth();\r\n\r\n // Listen for auth data from parent\r\n this.messageListener = (event: MessageEvent) => {\r\n // Validate origin if specified\r\n if (this.config.parentOrigin) {\r\n try {\r\n const parentUrl = new URL(this.config.parentOrigin);\r\n if (event.origin !== parentUrl.origin) {\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse parent origin, skip validation (development)\r\n }\r\n }\r\n\r\n // Handle auth data\r\n if (event.data?.type === 'OMENX_AUTH') {\r\n const authData = event.data.payload as AuthData;\r\n\r\n // Validate game ID\r\n if (authData.gameId !== this.config.gameId) {\r\n this.config.onError?.(new Error(`Game ID mismatch. Expected ${this.config.gameId}, got ${authData.gameId}`));\r\n return;\r\n }\r\n\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onError?.(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n this.config.onAuth(authData);\r\n }\r\n };\r\n\r\n window.addEventListener('message', this.messageListener);\r\n }\r\n\r\n /**\r\n * Request authentication data from parent window\r\n */\r\n private requestAuth(): void {\r\n if (window.parent === window) {\r\n // Not in an iframe\r\n return;\r\n }\r\n\r\n // Send request to parent\r\n const parentOrigin = this.config.parentOrigin || '*';\r\n window.parent.postMessage(\r\n {\r\n type: 'OMENX_AUTH_REQUEST',\r\n gameId: this.config.gameId,\r\n },\r\n parentOrigin\r\n );\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy(): void {\r\n if (this.messageListener) {\r\n window.removeEventListener('message', this.messageListener);\r\n this.messageListener = null;\r\n }\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\n/**\r\n * Manages token storage and retrieval\r\n */\r\nexport class TokenManager {\r\n private storageKeyPrefix: string;\r\n\r\n constructor(storageKeyPrefix: string = 'omenx_game_') {\r\n this.storageKeyPrefix = storageKeyPrefix;\r\n }\r\n\r\n /**\r\n * Store authentication data\r\n */\r\n storeAuth(authData: AuthData, refreshToken: string, expiresIn: number): void {\r\n try {\r\n localStorage.setItem(`${this.storageKeyPrefix}auth`, JSON.stringify(authData));\r\n localStorage.setItem(`${this.storageKeyPrefix}refresh_token`, refreshToken);\r\n localStorage.setItem(`${this.storageKeyPrefix}expires_at`, String(Date.now() + (expiresIn * 1000)));\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to store auth data:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Get stored authentication data\r\n */\r\n getStoredAuth(): AuthData | null {\r\n try {\r\n const stored = localStorage.getItem(`${this.storageKeyPrefix}auth`);\r\n if (!stored) {\r\n return null;\r\n }\r\n return JSON.parse(stored) as AuthData;\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve auth data:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get stored refresh token\r\n */\r\n getRefreshToken(): string | null {\r\n try {\r\n return localStorage.getItem(`${this.storageKeyPrefix}refresh_token`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve refresh token:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Clear all stored authentication data\r\n */\r\n clearStorage(): void {\r\n try {\r\n localStorage.removeItem(`${this.storageKeyPrefix}auth`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}refresh_token`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}expires_at`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to clear storage:', error);\r\n }\r\n }\r\n}\r\n","import type {\r\n OmenXGameSDKConfig,\r\n AuthData,\r\n OAuthOptions,\r\n OAuthTokenResponse,\r\n ApiCallOptions,\r\n} from './types';\r\nimport { OAuthFlow } from './oauth';\r\nimport { IframeAuth } from './iframe-auth';\r\nimport { TokenManager } from './token-manager';\r\n\r\n/**\r\n * OmenX Game SDK\r\n * \r\n * Provides authentication and API integration for games on the OmenX platform.\r\n * Supports both OAuth-style authentication and iframe authentication passing.\r\n */\r\nexport class OmenXGameSDK {\r\n private config: Required<OmenXGameSDKConfig>;\r\n private oauthFlow: OAuthFlow;\r\n private iframeAuth: IframeAuth | null = null;\r\n private tokenManager: TokenManager;\r\n private currentAuthData: AuthData | null = null;\r\n\r\n constructor(config: OmenXGameSDKConfig) {\r\n // Set defaults\r\n const apiBaseUrl = config.apiBaseUrl || 'https://api.omen.foundation';\r\n this.config = {\r\n gameId: config.gameId,\r\n apiBaseUrl: apiBaseUrl,\r\n oauthAuthorizeUrl: config.oauthAuthorizeUrl || `${apiBaseUrl}/v1/oauth/authorize`,\r\n oauthTokenUrl: config.oauthTokenUrl || `${apiBaseUrl}/v1/oauth/token`,\r\n onAuth: config.onAuth || (() => {}),\r\n onAuthError: config.onAuthError || ((error) => console.error('[OmenX SDK] Auth error:', error)),\r\n onLogout: config.onLogout || (() => {}),\r\n enableIframeAuth: config.enableIframeAuth !== false,\r\n parentOrigin: config.parentOrigin ?? '',\r\n storageKeyPrefix: config.storageKeyPrefix || 'omenx_game_',\r\n };\r\n\r\n // Initialize components\r\n this.tokenManager = new TokenManager(this.config.storageKeyPrefix);\r\n this.oauthFlow = new OAuthFlow({\r\n gameId: this.config.gameId,\r\n oauthAuthorizeUrl: this.config.oauthAuthorizeUrl,\r\n oauthTokenUrl: this.config.oauthTokenUrl,\r\n apiBaseUrl: this.config.apiBaseUrl,\r\n onTokenReceived: this.handleTokenReceived.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n\r\n if (this.config.enableIframeAuth) {\r\n this.iframeAuth = new IframeAuth({\r\n gameId: this.config.gameId,\r\n parentOrigin: this.config.parentOrigin || undefined,\r\n onAuth: this.handleAuthData.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Initialize the SDK\r\n * Call this after creating an instance\r\n */\r\n async init(): Promise<void> {\r\n // Try to restore from stored token\r\n const storedAuth = this.tokenManager.getStoredAuth();\r\n if (storedAuth) {\r\n // Check if token is still valid (not expired)\r\n const expiresAt = storedAuth.timestamp + (3600 * 1000); // 1 hour default\r\n if (Date.now() < expiresAt) {\r\n this.currentAuthData = storedAuth;\r\n this.config.onAuth(storedAuth);\r\n return;\r\n } else {\r\n // Token expired, try to refresh\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n return;\r\n } catch (error) {\r\n // Refresh failed, clear storage\r\n this.tokenManager.clearStorage();\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If iframe auth is enabled, try to get auth from parent\r\n if (this.config.enableIframeAuth && this.iframeAuth !== null) {\r\n this.iframeAuth.init();\r\n }\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<AuthData> {\r\n return this.oauthFlow.authenticate(options);\r\n }\r\n\r\n /**\r\n * Get current authentication data\r\n */\r\n getAuthData(): AuthData | null {\r\n return this.currentAuthData;\r\n }\r\n\r\n /**\r\n * Check if user is authenticated\r\n */\r\n isAuthenticated(): boolean {\r\n return this.currentAuthData !== null;\r\n }\r\n\r\n /**\r\n * Logout user\r\n */\r\n async logout(): Promise<void> {\r\n // Revoke token if we have one\r\n if (this.currentAuthData?.accessToken) {\r\n try {\r\n await this.apiCall('/v1/oauth/revoke', {\r\n method: 'POST',\r\n body: { token: this.currentAuthData.accessToken },\r\n includeAuth: false, // Don't include auth header for revoke\r\n });\r\n } catch (error) {\r\n // Ignore errors on revoke\r\n console.warn('[OmenX SDK] Failed to revoke token:', error);\r\n }\r\n }\r\n\r\n // Clear local state\r\n this.currentAuthData = null;\r\n this.tokenManager.clearStorage();\r\n this.config.onLogout();\r\n }\r\n\r\n /**\r\n * Make an authenticated API call\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...options.headers,\r\n };\r\n\r\n // Add authentication header if needed\r\n if (options.includeAuth !== false && this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n }\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n // If unauthorized, try to refresh token\r\n if (response.status === 401 && this.currentAuthData) {\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n // Retry the request with new token\r\n if (this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n return fetch(url, { ...fetchOptions, headers });\r\n }\r\n } catch (error) {\r\n // Refresh failed, logout\r\n await this.logout();\r\n throw new Error('Authentication expired. Please login again.');\r\n }\r\n }\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Handle token received from OAuth flow\r\n */\r\n private async handleTokenReceived(tokenResponse: OAuthTokenResponse): Promise<void> {\r\n const authData: AuthData = {\r\n accessToken: tokenResponse.access_token,\r\n walletAddress: tokenResponse.user.walletAddress,\r\n userId: tokenResponse.user.userId,\r\n profileName: tokenResponse.user.profileName,\r\n profilePicture: tokenResponse.user.profilePicture,\r\n email: tokenResponse.user.email,\r\n gameId: this.config.gameId,\r\n timestamp: Date.now(),\r\n };\r\n\r\n // Store tokens\r\n this.tokenManager.storeAuth(authData, tokenResponse.refresh_token, tokenResponse.expires_in);\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Handle auth data from iframe\r\n */\r\n private handleAuthData(authData: AuthData): void {\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onAuthError(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Refresh access token using refresh token\r\n */\r\n private async refreshAccessToken(refreshToken: string): Promise<void> {\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n grant_type: 'refresh_token',\r\n refresh_token: refreshToken,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error('Failed to refresh token');\r\n }\r\n\r\n const tokenResponse: OAuthTokenResponse = await response.json();\r\n await this.handleTokenReceived(tokenResponse);\r\n }\r\n}\r\n","import type { ApiCallOptions } from './types';\r\n\r\ninterface ServerSDKConfig {\r\n /**\r\n * Your developer API key (from developer portal)\r\n */\r\n apiKey: string;\r\n\r\n /**\r\n * OmenX API base URL (default: https://api.omen.foundation)\r\n */\r\n apiBaseUrl?: string;\r\n}\r\n\r\n/**\r\n * OmenX Game SDK - Server Mode\r\n * \r\n * For Node.js backends using developer API keys.\r\n * This mode allows server-to-server communication with the OmenX API.\r\n */\r\nexport class OmenXServerSDK {\r\n private config: Required<ServerSDKConfig>;\r\n private apiKey: string;\r\n\r\n constructor(config: ServerSDKConfig) {\r\n this.apiKey = config.apiKey;\r\n this.config = {\r\n apiKey: config.apiKey,\r\n apiBaseUrl: config.apiBaseUrl || 'https://api.omen.foundation',\r\n };\r\n }\r\n\r\n /**\r\n * Make an authenticated API call using the developer API key\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.apiKey}`,\r\n ...options.headers,\r\n };\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => 'Unknown error');\r\n throw new Error(`API call failed: ${response.status} ${response.statusText} - ${errorText}`);\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Health check\r\n */\r\n async healthCheck(): Promise<any> {\r\n const response = await this.apiCall('/v1/health', { includeAuth: false });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get API key information\r\n */\r\n async getApiKeyInfo(): Promise<any> {\r\n const response = await this.apiCall('/v1/auth/me');\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Player Operations\r\n */\r\n\r\n /**\r\n * Get native and ERC20 token balances for a wallet\r\n */\r\n async getPlayerBalances(wallet: string, chainId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/players/${wallet}/balances?chainId=${chainId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get paginated NFTs for a wallet\r\n */\r\n async getPlayerNfts(\r\n wallet: string,\r\n chainId: string,\r\n options?: {\r\n contract?: string;\r\n cursor?: string;\r\n limit?: number;\r\n }\r\n ): Promise<any> {\r\n const params = new URLSearchParams({ chainId });\r\n if (options?.contract) params.append('contract', options.contract);\r\n if (options?.cursor) params.append('cursor', options.cursor);\r\n if (options?.limit) params.append('limit', options.limit.toString());\r\n \r\n const response = await this.apiCall(`/v1/players/${wallet}/nfts?${params.toString()}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Purchase Operations\r\n */\r\n\r\n /**\r\n * Create a server-authoritative purchase\r\n */\r\n async createPurchase(params: {\r\n playerWallet?: string;\r\n walletAddress?: string; // Legacy field name\r\n skuId?: string;\r\n sku?: string; // Legacy field name\r\n quantity?: number;\r\n idempotencyKey?: string;\r\n paymentMethod?: string;\r\n metadata?: Record<string, any>;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/purchases', {\r\n method: 'POST',\r\n body: params,\r\n headers: params.idempotencyKey ? {\r\n 'Idempotency-Key': params.idempotencyKey,\r\n } : undefined,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * NFT Template Operations\r\n */\r\n\r\n /**\r\n * Get all NFT templates for a game\r\n */\r\n async getNftTemplates(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/templates?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get NFT contract address for a game\r\n */\r\n async getNftContract(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/contract?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Mint NFTs (single or batch)\r\n */\r\n async mintNfts(params: {\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch mint NFTs\r\n */\r\n async batchMintNfts(mints: Array<{\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }>): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint/batch', {\r\n method: 'POST',\r\n body: { mints },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Update NFT metadata\r\n */\r\n async updateNftMetadata(\r\n tokenId: string,\r\n metadata: {\r\n attributes?: Record<string, string | number | boolean>;\r\n name?: string;\r\n description?: string;\r\n imageUrl?: string;\r\n }\r\n ): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}/metadata`, {\r\n method: 'PUT',\r\n body: metadata,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Burn NFT (single)\r\n */\r\n async burnNft(tokenId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}`, {\r\n method: 'DELETE',\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch burn NFTs\r\n */\r\n async batchBurnNfts(tokenIds: string[]): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/burn/batch', {\r\n method: 'POST',\r\n body: { tokenIds },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Pack opener - mint random NFTs from a drop table\r\n */\r\n async packOpener(params: {\r\n dropTableId: string;\r\n recipientAddress: string;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/pack-opener', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n}\r\n"]}
1
+ {"version":3,"sources":["../src/pkce.ts","../src/oauth.ts","../src/iframe-auth.ts","../src/token-manager.ts","../src/sdk.ts","../src/server-sdk.ts"],"names":["codeVerifier"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * Generate PKCE (Proof Key for Code Exchange) code challenge and verifier\r\n */\r\nexport async function generatePKCE(): Promise<{ codeVerifier: string; codeChallenge: string }> {\r\n // Generate code verifier (43-128 characters, URL-safe)\r\n const codeVerifier = generateRandomString(128);\r\n\r\n // Generate code challenge (SHA256 hash of code verifier, base64url encoded)\r\n const hash = await sha256(codeVerifier);\r\n const codeChallenge = base64URLEncode(hash);\r\n\r\n return { codeVerifier, codeChallenge };\r\n}\r\n\r\n/**\r\n * Generate random URL-safe string\r\n */\r\nfunction generateRandomString(length: number): string {\r\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\r\n const array = new Uint8Array(length);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => charset[byte % charset.length]).join('');\r\n}\r\n\r\n/**\r\n * Base64 URL encode (without padding)\r\n */\r\nfunction base64URLEncode(buffer: ArrayBuffer): string {\r\n const base64 = btoa(String.fromCharCode(...new Uint8Array(buffer)));\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\r\n}\r\n\r\n/**\r\n * SHA256 hash\r\n */\r\nasync function sha256(message: string): Promise<ArrayBuffer> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(message);\r\n return crypto.subtle.digest('SHA-256', data);\r\n}\r\n","import type { OAuthOptions, OAuthTokenResponse } from './types';\r\nimport { generatePKCE } from './pkce';\r\n\r\ninterface OAuthFlowConfig {\r\n gameId: string;\r\n oauthAuthorizeUrl: string;\r\n oauthTokenUrl: string;\r\n apiBaseUrl: string;\r\n onTokenReceived: (tokenResponse: OAuthTokenResponse) => Promise<void>;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles OAuth 2.0 Authorization Code Grant flow with PKCE\r\n */\r\nexport class OAuthFlow {\r\n private config: OAuthFlowConfig;\r\n\r\n constructor(config: OAuthFlowConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<any> {\r\n // Generate state for CSRF protection\r\n const state = options.state || this.generateState();\r\n \r\n // CRITICAL: Clean up old OAuth callback entries from localStorage\r\n // This prevents state mismatches when starting a new flow\r\n try {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n console.log('[OAuthFlow] ๐Ÿงน Cleaning up old OAuth entries:', { count: allKeys.length });\r\n allKeys.forEach(key => {\r\n try {\r\n const data = localStorage.getItem(key);\r\n if (data) {\r\n const parsed = JSON.parse(data);\r\n const age = Date.now() - (parsed.timestamp || 0);\r\n // Remove entries older than 5 minutes\r\n if (age > 300000) {\r\n localStorage.removeItem(key);\r\n console.log('[OAuthFlow] ๐Ÿ—‘๏ธ Removed old entry:', key.substring(0, 50) + '...', { age: `${age}ms` });\r\n }\r\n }\r\n } catch (e) {\r\n // If we can't parse it, remove it anyway\r\n localStorage.removeItem(key);\r\n }\r\n });\r\n } catch (error) {\r\n console.warn('[OAuthFlow] โš ๏ธ Error cleaning up old entries:', error);\r\n }\r\n \r\n // Generate PKCE if enabled\r\n let codeChallenge: string | undefined;\r\n let codeVerifier: string | undefined;\r\n if (options.enablePKCE !== false) {\r\n const pkce = await generatePKCE();\r\n codeChallenge = pkce.codeChallenge;\r\n codeVerifier = pkce.codeVerifier;\r\n // Store code verifier for later use\r\n sessionStorage.setItem(`omenx_pkce_${state}`, codeVerifier);\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n // Build authorization URL\r\n const params = new URLSearchParams({\r\n client_id: this.config.gameId,\r\n redirect_uri: options.redirectUri,\r\n response_type: 'code',\r\n state: state,\r\n });\r\n\r\n if (codeChallenge) {\r\n params.append('code_challenge', codeChallenge);\r\n params.append('code_challenge_method', 'S256');\r\n }\r\n\r\n const authUrl = `${this.config.oauthAuthorizeUrl}?${params.toString()}`;\r\n\r\n // Open popup window\r\n const popup = window.open(\r\n authUrl,\r\n 'OmenX Authentication',\r\n 'width=500,height=600,left=' + (window.screen.width / 2 - 250) + ',top=' + (window.screen.height / 2 - 300)\r\n );\r\n\r\n if (!popup) {\r\n const error = new Error('Failed to open popup window. Please allow popups for this site.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Listen for authorization code\r\n const messageListener = async (event: MessageEvent) => {\r\n // Validate origin - the callback page is on the game's domain, not the OAuth server\r\n // We should check that the message comes from the same origin as the current window\r\n // (the game's domain where the callback page is hosted)\r\n try {\r\n // The callback page is on the game's domain, so check against current origin\r\n const currentOrigin = window.location.origin;\r\n if (event.origin !== currentOrigin) {\r\n // Message not from our domain - ignore it\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse the URL, skip origin check (development)\r\n }\r\n\r\n if (event.data?.type === 'OMENX_OAUTH_CODE') {\r\n window.removeEventListener('message', messageListener);\r\n popup.close();\r\n\r\n const { code, state: returnedState } = event.data;\r\n\r\n // Validate state\r\n if (returnedState !== state) {\r\n const error = new Error('Invalid state parameter. Possible CSRF attack.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n return;\r\n }\r\n\r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n\r\n try {\r\n // Exchange code for token\r\n const tokenResponse = await this.exchangeCodeForToken(code, options.redirectUri, codeVerifier);\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n } catch (error) {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n }\r\n }\r\n };\r\n\r\n window.addEventListener('message', messageListener);\r\n\r\n // Also listen for localStorage events as fallback (in case window.opener is lost)\r\n // The callback page will store the code in localStorage if postMessage fails\r\n const storageListener = (event: StorageEvent) => {\r\n if (!event.key || !event.key.startsWith('omenx_oauth_callback_')) {\r\n return;\r\n }\r\n \r\n const callbackState = event.key.replace('omenx_oauth_callback_', '');\r\n if (callbackState !== state) {\r\n return; // Not our callback\r\n }\r\n \r\n try {\r\n const data = JSON.parse(event.newValue || '{}');\r\n if (data.code && data.state === state) {\r\n console.log('[OAuthFlow] Received OAuth code via localStorage fallback');\r\n messageReceived = true;\r\n window.removeEventListener('storage', storageListener);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n \r\n // Process the code the same way as postMessage\r\n const { code: codeFromStorage } = data;\r\n \r\n // Get code verifier if PKCE was used\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n // Exchange code for token\r\n this.exchangeCodeForToken(codeFromStorage, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n \r\n // Clean up localStorage\r\n localStorage.removeItem(event.key!);\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] Error processing localStorage callback:', error);\r\n }\r\n };\r\n \r\n window.addEventListener('storage', storageListener);\r\n \r\n // Also poll localStorage as additional fallback (storage events don't fire in same window)\r\n // This is critical because when the popup closes, storage events might not fire\r\n let pollCount = 0;\r\n const storageKey = `omenx_oauth_callback_${state}`;\r\n \r\n // Immediately check localStorage on first poll (before interval starts)\r\n // This helps catch callback data that was stored before polling started\r\n const immediateCheck = () => {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n console.log('[OAuthFlow] ๐Ÿ” Immediate localStorage check:', { \r\n count: allKeys.length,\r\n keys: allKeys.map(k => k.substring(0, 50) + '...'),\r\n lookingFor: storageKey.substring(0, 50) + '...',\r\n expectedState: state.substring(0, 20) + '...'\r\n });\r\n \r\n // Try to find a match by checking each key\r\n for (const key of allKeys) {\r\n const storedData = localStorage.getItem(key);\r\n if (storedData) {\r\n try {\r\n const data = JSON.parse(storedData);\r\n console.log('[OAuthFlow] ๐Ÿ” Checking stored key:', {\r\n key: key.substring(0, 50) + '...',\r\n storedState: data.state?.substring(0, 20) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n statesMatch: data.state === state,\r\n hasCode: !!data.code,\r\n timestamp: data.timestamp,\r\n age: data.timestamp ? `${Date.now() - data.timestamp}ms` : 'unknown'\r\n });\r\n } catch (e) {\r\n console.warn('[OAuthFlow] โš ๏ธ Error parsing stored key:', key, e);\r\n }\r\n }\r\n }\r\n };\r\n \r\n // Run immediate check\r\n immediateCheck();\r\n \r\n // Log that polling is starting\r\n console.log('[OAuthFlow] ๐Ÿ”„ Starting localStorage polling interval (every 100ms)');\r\n \r\n const pollInterval = setInterval(() => {\r\n pollCount++;\r\n const stored = localStorage.getItem(storageKey);\r\n \r\n // Log every 1 second (10 * 100ms) for debugging - ALWAYS log to prove polling is running\r\n if (pollCount % 10 === 0) {\r\n console.log('[OAuthFlow] ๐Ÿ” Polling localStorage...', { \r\n key: storageKey.substring(0, 50) + '...',\r\n found: !!stored, \r\n pollCount,\r\n statePreview: state.substring(0, 20) + '...',\r\n intervalActive: true\r\n });\r\n \r\n // Re-check all keys every 10 seconds for debugging\r\n if (pollCount % 100 === 0) {\r\n immediateCheck();\r\n }\r\n }\r\n \r\n // ALWAYS check if we found the data (not just log every 10 polls)\r\n if (stored) {\r\n try {\r\n const data = JSON.parse(stored);\r\n \r\n // Log immediately when we find data (not just every 10 polls)\r\n if (pollCount === 1 || pollCount % 10 === 0) {\r\n console.log('[OAuthFlow] โœ… Found stored data!', { \r\n hasCode: !!data.code,\r\n hasState: !!data.state,\r\n stateMatch: data.state === state,\r\n storedState: data.state?.substring(0, 20) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n pollCount\r\n });\r\n }\r\n \r\n if (data.code && data.state === state) {\r\n const age = Date.now() - (data.timestamp || 0);\r\n if (age < 30000) { // 30 second timeout\r\n console.log('[OAuthFlow] โœ…โœ…โœ… Processing OAuth callback from localStorage!', { \r\n age: `${age}ms`, \r\n hasCode: !!data.code,\r\n codePreview: data.code.substring(0, 10) + '...',\r\n pollCount\r\n });\r\n // Found callback data, trigger storage event manually\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n // Note: broadcastChannel cleanup will happen in checkClosed interval\r\n storageListener(new StorageEvent('storage', {\r\n key: storageKey,\r\n newValue: stored,\r\n storageArea: localStorage,\r\n }));\r\n return; // Exit early to prevent further processing\r\n } else {\r\n console.warn('[OAuthFlow] โš ๏ธ Callback data too old, removing:', { age: `${age}ms` });\r\n localStorage.removeItem(storageKey);\r\n }\r\n } else {\r\n // Log state mismatch immediately when found\r\n console.warn('[OAuthFlow] โš ๏ธ State mismatch!', {\r\n storedState: data.state?.substring(0, 20) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n statesMatch: data.state === state,\r\n storedStateLength: data.state?.length,\r\n expectedStateLength: state.length,\r\n pollCount\r\n });\r\n }\r\n } catch (error) {\r\n console.error('[OAuthFlow] โŒ Error parsing localStorage callback:', error, { \r\n stored: stored?.substring(0, 100) + '...',\r\n pollCount \r\n });\r\n }\r\n } else {\r\n // Also check for ANY omenx_oauth_callback keys if we haven't found our specific key\r\n // This helps catch cases where the key format is slightly different\r\n // Check more frequently (every 5 polls = 500ms) to catch the callback quickly\r\n if (pollCount === 1 || pollCount % 5 === 0) {\r\n const allKeys = Object.keys(localStorage).filter(k => k.startsWith('omenx_oauth_callback_'));\r\n if (allKeys.length > 0) {\r\n console.log('[OAuthFlow] ๐Ÿ” Found localStorage keys (checking all for state match):', { \r\n count: allKeys.length,\r\n keys: allKeys.map(k => k.substring(0, 50) + '...'),\r\n lookingFor: storageKey.substring(0, 50) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n pollCount\r\n });\r\n \r\n // Check each key to see if any match our state (by value, not just key name)\r\n for (const key of allKeys) {\r\n const storedData = localStorage.getItem(key);\r\n if (storedData) {\r\n try {\r\n const data = JSON.parse(storedData);\r\n const statesMatch = data.state === state;\r\n console.log('[OAuthFlow] ๐Ÿ” Checking stored key:', {\r\n key: key.substring(0, 50) + '...',\r\n storedState: data.state?.substring(0, 20) + '...',\r\n expectedState: state.substring(0, 20) + '...',\r\n statesMatch: statesMatch,\r\n storedStateLength: data.state?.length,\r\n expectedStateLength: state.length,\r\n hasCode: !!data.code,\r\n pollCount\r\n });\r\n \r\n // If state matches, process it even if the key name doesn't match exactly\r\n if (statesMatch && data.code) {\r\n const age = Date.now() - (data.timestamp || 0);\r\n if (age < 30000) {\r\n console.log('[OAuthFlow] โœ…โœ…โœ… Found matching state in different key! Processing...', {\r\n key: key.substring(0, 50) + '...',\r\n age: `${age}ms`,\r\n pollCount\r\n });\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n // Process the callback\r\n storageListener(new StorageEvent('storage', {\r\n key: key,\r\n newValue: storedData,\r\n storageArea: localStorage,\r\n }));\r\n return;\r\n }\r\n }\r\n } catch (e) {\r\n console.warn('[OAuthFlow] โš ๏ธ Error parsing key:', key, e);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }, 100); // Poll every 100ms\r\n \r\n // Also listen for BroadcastChannel as another fallback\r\n let broadcastChannel: BroadcastChannel | null = null;\r\n try {\r\n broadcastChannel = new BroadcastChannel('omenx_oauth');\r\n const broadcastListener = (event: MessageEvent) => {\r\n if (event.data?.type === 'OMENX_OAUTH_CODE' && event.data?.state === state) {\r\n console.log('[OAuthFlow] โœ… Received OAuth code via BroadcastChannel');\r\n messageReceived = true;\r\n clearInterval(pollInterval);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n \r\n const { code: codeFromBroadcast } = event.data;\r\n const storedCodeVerifier = sessionStorage.getItem(`omenx_pkce_${state}`);\r\n let codeVerifier: string | undefined;\r\n if (storedCodeVerifier) {\r\n sessionStorage.removeItem(`omenx_pkce_${state}`);\r\n codeVerifier = storedCodeVerifier;\r\n }\r\n \r\n this.exchangeCodeForToken(codeFromBroadcast, options.redirectUri, codeVerifier)\r\n .then(async (tokenResponse) => {\r\n await this.config.onTokenReceived(tokenResponse);\r\n resolve(tokenResponse);\r\n })\r\n .catch((error) => {\r\n this.config.onError?.(error as Error);\r\n reject(error);\r\n });\r\n }\r\n };\r\n // BroadcastChannel uses onmessage, not addEventListener\r\n broadcastChannel.onmessage = broadcastListener;\r\n \r\n // Clean up will happen in checkClosed interval\r\n } catch (error) {\r\n console.warn('[OAuthFlow] BroadcastChannel not supported:', error);\r\n broadcastChannel = null;\r\n }\r\n \r\n // Log that we're starting to listen for OAuth callback\r\n console.log('[OAuthFlow] ๐Ÿ” Starting OAuth flow, listening for callback...', { \r\n state: state,\r\n statePreview: state.substring(0, 20) + '...',\r\n stateLength: state.length,\r\n hasOpener: !!window.opener,\r\n polling: true,\r\n broadcastChannel: true,\r\n expectedKey: `omenx_oauth_callback_${state}`\r\n });\r\n \r\n // Check if popup was closed\r\n // Only report cancellation if we haven't received a message yet\r\n let messageReceived = false;\r\n const originalMessageListener = messageListener;\r\n const wrappedMessageListener = async (event: MessageEvent) => {\r\n messageReceived = true;\r\n // Clean up listeners when message is received\r\n clearInterval(pollInterval);\r\n window.removeEventListener('storage', storageListener);\r\n await originalMessageListener(event);\r\n };\r\n window.removeEventListener('message', messageListener);\r\n window.addEventListener('message', wrappedMessageListener);\r\n \r\n /**\r\n * Check if popup is actually closed (not just on a different origin)\r\n * When a popup navigates to a different domain, popup.closed might be true\r\n * due to cross-origin restrictions, but the popup is still open.\r\n * We can detect this by trying to access popup.location - if it throws,\r\n * the popup is still open but on a different origin.\r\n */\r\n const isPopupActuallyClosed = (): boolean => {\r\n try {\r\n // If popup.closed is false, it's definitely still open\r\n if (!popup.closed) {\r\n return false;\r\n }\r\n \r\n // If popup.closed is true, we need to verify it's actually closed\r\n // by trying to access its location\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n const _ = popup.location.href;\r\n // If we can access location, popup is on same origin and closed\r\n return true;\r\n } catch (e) {\r\n // If accessing location throws, popup is on different origin (still open)\r\n // This is normal during OAuth flow when popup navigates to OAuth server\r\n return false;\r\n }\r\n } catch (e) {\r\n // If we can't check at all, assume popup is still open to be safe\r\n return false;\r\n }\r\n };\r\n \r\n // Track when popup appears closed - give grace period for callback to complete\r\n let popupClosedTime: number | null = null;\r\n const POPUP_CLOSED_GRACE_PERIOD = 5000; // 5 seconds grace period\r\n \r\n const checkClosed = setInterval(() => {\r\n // Skip check if we've already received a message\r\n if (messageReceived) {\r\n clearInterval(checkClosed);\r\n clearInterval(pollInterval);\r\n return;\r\n }\r\n \r\n // Check if popup is actually closed (handles cross-origin correctly)\r\n if (isPopupActuallyClosed()) {\r\n // First time we detect popup is closed - start grace period\r\n if (popupClosedTime === null) {\r\n popupClosedTime = Date.now();\r\n console.log('[OAuthFlow] โš ๏ธ Popup appears closed, starting grace period for callback...', {\r\n gracePeriod: `${POPUP_CLOSED_GRACE_PERIOD}ms`,\r\n pollCount,\r\n stillPolling: true\r\n });\r\n return; // Don't cancel yet - give callback time to complete\r\n }\r\n \r\n // Check if grace period has expired\r\n const timeSinceClosed = Date.now() - popupClosedTime;\r\n if (timeSinceClosed < POPUP_CLOSED_GRACE_PERIOD) {\r\n // Still in grace period - keep polling\r\n console.log('[OAuthFlow] โณ Popup closed, but still in grace period...', {\r\n timeRemaining: `${POPUP_CLOSED_GRACE_PERIOD - timeSinceClosed}ms`,\r\n pollCount\r\n });\r\n return;\r\n }\r\n \r\n // Grace period expired - popup is truly closed without callback\r\n console.log('[OAuthFlow] โŒ Popup closed and grace period expired without callback', {\r\n timeSinceClosed: `${timeSinceClosed}ms`,\r\n pollCount,\r\n finalCheck: 'Checking localStorage one last time...'\r\n });\r\n \r\n // Final check of localStorage before giving up\r\n immediateCheck();\r\n \r\n clearInterval(checkClosed);\r\n clearInterval(pollInterval);\r\n window.removeEventListener('message', wrappedMessageListener);\r\n window.removeEventListener('storage', storageListener);\r\n if (broadcastChannel) {\r\n broadcastChannel.onmessage = null;\r\n broadcastChannel.close();\r\n }\r\n \r\n // Only report cancellation if we haven't received a message\r\n if (!messageReceived) {\r\n const error = new Error('Authentication was cancelled.');\r\n this.config.onError?.(error);\r\n reject(error);\r\n }\r\n } else {\r\n // Popup is still open - reset closed time\r\n if (popupClosedTime !== null) {\r\n console.log('[OAuthFlow] โœ… Popup is open again (was temporarily on different origin)');\r\n popupClosedTime = null;\r\n }\r\n }\r\n }, 1000);\r\n });\r\n }\r\n\r\n /**\r\n * Exchange authorization code for access token\r\n */\r\n private async exchangeCodeForToken(\r\n code: string,\r\n redirectUri: string,\r\n codeVerifier?: string\r\n ): Promise<OAuthTokenResponse> {\r\n const body: any = {\r\n code,\r\n redirect_uri: redirectUri,\r\n grant_type: 'authorization_code',\r\n };\r\n\r\n if (codeVerifier) {\r\n body.code_verifier = codeVerifier;\r\n }\r\n\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n // Note: API key should be included via Authorization header\r\n // This should be set by the game's backend, not the SDK\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n\r\n if (!response.ok) {\r\n const error = await response.json().catch(() => ({ message: 'Failed to exchange code for token' }));\r\n throw new Error(error.message || 'Failed to exchange code for token');\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Generate random state for CSRF protection\r\n */\r\n private generateState(): string {\r\n const array = new Uint8Array(32);\r\n crypto.getRandomValues(array);\r\n return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\ninterface IframeAuthConfig {\r\n gameId: string;\r\n parentOrigin?: string;\r\n onAuth: (authData: AuthData) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Handles authentication data passed from parent window via postMessage\r\n */\r\nexport class IframeAuth {\r\n private config: IframeAuthConfig;\r\n private messageListener: ((event: MessageEvent) => void) | null = null;\r\n\r\n constructor(config: IframeAuthConfig) {\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Initialize iframe authentication listener\r\n */\r\n init(): void {\r\n // Request auth data from parent\r\n this.requestAuth();\r\n\r\n // Listen for auth data from parent\r\n this.messageListener = (event: MessageEvent) => {\r\n // Validate origin if specified\r\n if (this.config.parentOrigin) {\r\n try {\r\n const parentUrl = new URL(this.config.parentOrigin);\r\n if (event.origin !== parentUrl.origin) {\r\n return;\r\n }\r\n } catch {\r\n // If we can't parse parent origin, skip validation (development)\r\n }\r\n }\r\n\r\n // Handle auth data\r\n if (event.data?.type === 'OMENX_AUTH') {\r\n const authData = event.data.payload as AuthData;\r\n\r\n // Validate game ID\r\n if (authData.gameId !== this.config.gameId) {\r\n this.config.onError?.(new Error(`Game ID mismatch. Expected ${this.config.gameId}, got ${authData.gameId}`));\r\n return;\r\n }\r\n\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onError?.(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n this.config.onAuth(authData);\r\n }\r\n };\r\n\r\n window.addEventListener('message', this.messageListener);\r\n }\r\n\r\n /**\r\n * Request authentication data from parent window\r\n */\r\n private requestAuth(): void {\r\n if (window.parent === window) {\r\n // Not in an iframe\r\n return;\r\n }\r\n\r\n // Send request to parent\r\n const parentOrigin = this.config.parentOrigin || '*';\r\n window.parent.postMessage(\r\n {\r\n type: 'OMENX_AUTH_REQUEST',\r\n gameId: this.config.gameId,\r\n },\r\n parentOrigin\r\n );\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy(): void {\r\n if (this.messageListener) {\r\n window.removeEventListener('message', this.messageListener);\r\n this.messageListener = null;\r\n }\r\n }\r\n}\r\n","import type { AuthData } from './types';\r\n\r\n/**\r\n * Manages token storage and retrieval\r\n */\r\nexport class TokenManager {\r\n private storageKeyPrefix: string;\r\n\r\n constructor(storageKeyPrefix: string = 'omenx_game_') {\r\n this.storageKeyPrefix = storageKeyPrefix;\r\n }\r\n\r\n /**\r\n * Store authentication data\r\n */\r\n storeAuth(authData: AuthData, refreshToken: string, expiresIn: number): void {\r\n try {\r\n localStorage.setItem(`${this.storageKeyPrefix}auth`, JSON.stringify(authData));\r\n localStorage.setItem(`${this.storageKeyPrefix}refresh_token`, refreshToken);\r\n localStorage.setItem(`${this.storageKeyPrefix}expires_at`, String(Date.now() + (expiresIn * 1000)));\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to store auth data:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Get stored authentication data\r\n */\r\n getStoredAuth(): AuthData | null {\r\n try {\r\n const stored = localStorage.getItem(`${this.storageKeyPrefix}auth`);\r\n if (!stored) {\r\n return null;\r\n }\r\n return JSON.parse(stored) as AuthData;\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve auth data:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get stored refresh token\r\n */\r\n getRefreshToken(): string | null {\r\n try {\r\n return localStorage.getItem(`${this.storageKeyPrefix}refresh_token`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to retrieve refresh token:', error);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Clear all stored authentication data\r\n */\r\n clearStorage(): void {\r\n try {\r\n localStorage.removeItem(`${this.storageKeyPrefix}auth`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}refresh_token`);\r\n localStorage.removeItem(`${this.storageKeyPrefix}expires_at`);\r\n } catch (error) {\r\n console.warn('[TokenManager] Failed to clear storage:', error);\r\n }\r\n }\r\n}\r\n","import type {\r\n OmenXGameSDKConfig,\r\n AuthData,\r\n OAuthOptions,\r\n OAuthTokenResponse,\r\n ApiCallOptions,\r\n} from './types';\r\nimport { OAuthFlow } from './oauth';\r\nimport { IframeAuth } from './iframe-auth';\r\nimport { TokenManager } from './token-manager';\r\n\r\n/**\r\n * OmenX Game SDK\r\n * \r\n * Provides authentication and API integration for games on the OmenX platform.\r\n * Supports both OAuth-style authentication and iframe authentication passing.\r\n */\r\nexport class OmenXGameSDK {\r\n private config: Required<OmenXGameSDKConfig>;\r\n private oauthFlow: OAuthFlow;\r\n private iframeAuth: IframeAuth | null = null;\r\n private tokenManager: TokenManager;\r\n private currentAuthData: AuthData | null = null;\r\n\r\n constructor(config: OmenXGameSDKConfig) {\r\n // Set defaults\r\n const apiBaseUrl = config.apiBaseUrl || 'https://api.omen.foundation';\r\n this.config = {\r\n gameId: config.gameId,\r\n apiBaseUrl: apiBaseUrl,\r\n oauthAuthorizeUrl: config.oauthAuthorizeUrl || `${apiBaseUrl}/v1/oauth/authorize`,\r\n oauthTokenUrl: config.oauthTokenUrl || `${apiBaseUrl}/v1/oauth/token`,\r\n onAuth: config.onAuth || (() => {}),\r\n onAuthError: config.onAuthError || ((error) => console.error('[OmenX SDK] Auth error:', error)),\r\n onLogout: config.onLogout || (() => {}),\r\n enableIframeAuth: config.enableIframeAuth !== false,\r\n parentOrigin: config.parentOrigin ?? '',\r\n storageKeyPrefix: config.storageKeyPrefix || 'omenx_game_',\r\n };\r\n\r\n // Initialize components\r\n this.tokenManager = new TokenManager(this.config.storageKeyPrefix);\r\n this.oauthFlow = new OAuthFlow({\r\n gameId: this.config.gameId,\r\n oauthAuthorizeUrl: this.config.oauthAuthorizeUrl,\r\n oauthTokenUrl: this.config.oauthTokenUrl,\r\n apiBaseUrl: this.config.apiBaseUrl,\r\n onTokenReceived: this.handleTokenReceived.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n\r\n if (this.config.enableIframeAuth) {\r\n this.iframeAuth = new IframeAuth({\r\n gameId: this.config.gameId,\r\n parentOrigin: this.config.parentOrigin || undefined,\r\n onAuth: this.handleAuthData.bind(this),\r\n onError: this.config.onAuthError,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Initialize the SDK\r\n * Call this after creating an instance\r\n */\r\n async init(): Promise<void> {\r\n // Try to restore from stored token\r\n const storedAuth = this.tokenManager.getStoredAuth();\r\n if (storedAuth) {\r\n // Check if token is still valid (not expired)\r\n const expiresAt = storedAuth.timestamp + (3600 * 1000); // 1 hour default\r\n if (Date.now() < expiresAt) {\r\n this.currentAuthData = storedAuth;\r\n this.config.onAuth(storedAuth);\r\n return;\r\n } else {\r\n // Token expired, try to refresh\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n return;\r\n } catch (error) {\r\n // Refresh failed, clear storage\r\n this.tokenManager.clearStorage();\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If iframe auth is enabled, try to get auth from parent\r\n if (this.config.enableIframeAuth && this.iframeAuth !== null) {\r\n this.iframeAuth.init();\r\n }\r\n }\r\n\r\n /**\r\n * Authenticate user via OAuth popup\r\n */\r\n async authenticate(options: OAuthOptions): Promise<AuthData> {\r\n return this.oauthFlow.authenticate(options);\r\n }\r\n\r\n /**\r\n * Get current authentication data\r\n */\r\n getAuthData(): AuthData | null {\r\n return this.currentAuthData;\r\n }\r\n\r\n /**\r\n * Check if user is authenticated\r\n */\r\n isAuthenticated(): boolean {\r\n return this.currentAuthData !== null;\r\n }\r\n\r\n /**\r\n * Logout user\r\n */\r\n async logout(): Promise<void> {\r\n // Revoke token if we have one\r\n if (this.currentAuthData?.accessToken) {\r\n try {\r\n await this.apiCall('/v1/oauth/revoke', {\r\n method: 'POST',\r\n body: { token: this.currentAuthData.accessToken },\r\n includeAuth: false, // Don't include auth header for revoke\r\n });\r\n } catch (error) {\r\n // Ignore errors on revoke\r\n console.warn('[OmenX SDK] Failed to revoke token:', error);\r\n }\r\n }\r\n\r\n // Clear local state\r\n this.currentAuthData = null;\r\n this.tokenManager.clearStorage();\r\n this.config.onLogout();\r\n }\r\n\r\n /**\r\n * Make an authenticated API call\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...options.headers,\r\n };\r\n\r\n // Add authentication header if needed\r\n if (options.includeAuth !== false && this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n }\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n // If unauthorized, try to refresh token\r\n if (response.status === 401 && this.currentAuthData) {\r\n const refreshToken = this.tokenManager.getRefreshToken();\r\n if (refreshToken) {\r\n try {\r\n await this.refreshAccessToken(refreshToken);\r\n // Retry the request with new token\r\n if (this.currentAuthData?.accessToken) {\r\n headers['Authorization'] = `Bearer ${this.currentAuthData.accessToken}`;\r\n return fetch(url, { ...fetchOptions, headers });\r\n }\r\n } catch (error) {\r\n // Refresh failed, logout\r\n await this.logout();\r\n throw new Error('Authentication expired. Please login again.');\r\n }\r\n }\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Handle token received from OAuth flow\r\n */\r\n private async handleTokenReceived(tokenResponse: OAuthTokenResponse): Promise<void> {\r\n const authData: AuthData = {\r\n accessToken: tokenResponse.access_token,\r\n walletAddress: tokenResponse.user.walletAddress,\r\n userId: tokenResponse.user.userId,\r\n profileName: tokenResponse.user.profileName,\r\n profilePicture: tokenResponse.user.profilePicture,\r\n email: tokenResponse.user.email,\r\n gameId: this.config.gameId,\r\n timestamp: Date.now(),\r\n };\r\n\r\n // Store tokens\r\n this.tokenManager.storeAuth(authData, tokenResponse.refresh_token, tokenResponse.expires_in);\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Handle auth data from iframe\r\n */\r\n private handleAuthData(authData: AuthData): void {\r\n // Validate timestamp (5 minute expiry)\r\n const fiveMinutesAgo = Date.now() - (5 * 60 * 1000);\r\n if (authData.timestamp < fiveMinutesAgo) {\r\n this.config.onAuthError(new Error('Auth data expired'));\r\n return;\r\n }\r\n\r\n // Update current auth\r\n this.currentAuthData = authData;\r\n this.config.onAuth(authData);\r\n }\r\n\r\n /**\r\n * Refresh access token using refresh token\r\n */\r\n private async refreshAccessToken(refreshToken: string): Promise<void> {\r\n const response = await fetch(this.config.oauthTokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n grant_type: 'refresh_token',\r\n refresh_token: refreshToken,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error('Failed to refresh token');\r\n }\r\n\r\n const tokenResponse: OAuthTokenResponse = await response.json();\r\n await this.handleTokenReceived(tokenResponse);\r\n }\r\n}\r\n","import type { ApiCallOptions } from './types';\r\n\r\ninterface ServerSDKConfig {\r\n /**\r\n * Your developer API key (from developer portal)\r\n */\r\n apiKey: string;\r\n\r\n /**\r\n * OmenX API base URL (default: https://api.omen.foundation)\r\n */\r\n apiBaseUrl?: string;\r\n}\r\n\r\n/**\r\n * OmenX Game SDK - Server Mode\r\n * \r\n * For Node.js backends using developer API keys.\r\n * This mode allows server-to-server communication with the OmenX API.\r\n */\r\nexport class OmenXServerSDK {\r\n private config: Required<ServerSDKConfig>;\r\n private apiKey: string;\r\n\r\n constructor(config: ServerSDKConfig) {\r\n this.apiKey = config.apiKey;\r\n this.config = {\r\n apiKey: config.apiKey,\r\n apiBaseUrl: config.apiBaseUrl || 'https://api.omen.foundation',\r\n };\r\n }\r\n\r\n /**\r\n * Make an authenticated API call using the developer API key\r\n */\r\n async apiCall(endpoint: string, options: ApiCallOptions = {}): Promise<Response> {\r\n const url = endpoint.startsWith('http') \r\n ? endpoint \r\n : `${this.config.apiBaseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;\r\n\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.apiKey}`,\r\n ...options.headers,\r\n };\r\n\r\n const fetchOptions: RequestInit = {\r\n method: options.method || 'GET',\r\n headers,\r\n };\r\n\r\n if (options.body && options.method !== 'GET') {\r\n fetchOptions.body = JSON.stringify(options.body);\r\n }\r\n\r\n const response = await fetch(url, fetchOptions);\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => 'Unknown error');\r\n throw new Error(`API call failed: ${response.status} ${response.statusText} - ${errorText}`);\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Health check\r\n */\r\n async healthCheck(): Promise<any> {\r\n const response = await this.apiCall('/v1/health', { includeAuth: false });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get API key information\r\n */\r\n async getApiKeyInfo(): Promise<any> {\r\n const response = await this.apiCall('/v1/auth/me');\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Player Operations\r\n */\r\n\r\n /**\r\n * Get native and ERC20 token balances for a wallet\r\n */\r\n async getPlayerBalances(wallet: string, chainId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/players/${wallet}/balances?chainId=${chainId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get paginated NFTs for a wallet\r\n */\r\n async getPlayerNfts(\r\n wallet: string,\r\n chainId: string,\r\n options?: {\r\n contract?: string;\r\n cursor?: string;\r\n limit?: number;\r\n }\r\n ): Promise<any> {\r\n const params = new URLSearchParams({ chainId });\r\n if (options?.contract) params.append('contract', options.contract);\r\n if (options?.cursor) params.append('cursor', options.cursor);\r\n if (options?.limit) params.append('limit', options.limit.toString());\r\n \r\n const response = await this.apiCall(`/v1/players/${wallet}/nfts?${params.toString()}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Purchase Operations\r\n */\r\n\r\n /**\r\n * Create a server-authoritative purchase\r\n */\r\n async createPurchase(params: {\r\n playerWallet?: string;\r\n walletAddress?: string; // Legacy field name\r\n skuId?: string;\r\n sku?: string; // Legacy field name\r\n quantity?: number;\r\n idempotencyKey?: string;\r\n paymentMethod?: string;\r\n metadata?: Record<string, any>;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/purchases', {\r\n method: 'POST',\r\n body: params,\r\n headers: params.idempotencyKey ? {\r\n 'Idempotency-Key': params.idempotencyKey,\r\n } : undefined,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * NFT Template Operations\r\n */\r\n\r\n /**\r\n * Get all NFT templates for a game\r\n */\r\n async getNftTemplates(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/templates?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get NFT contract address for a game\r\n */\r\n async getNftContract(gameId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/contract?gameId=${gameId}`);\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Mint NFTs (single or batch)\r\n */\r\n async mintNfts(params: {\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch mint NFTs\r\n */\r\n async batchMintNfts(mints: Array<{\r\n templateId: string;\r\n recipientAddress: string;\r\n quantity: number;\r\n }>): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/mint/batch', {\r\n method: 'POST',\r\n body: { mints },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Update NFT metadata\r\n */\r\n async updateNftMetadata(\r\n tokenId: string,\r\n metadata: {\r\n attributes?: Record<string, string | number | boolean>;\r\n name?: string;\r\n description?: string;\r\n imageUrl?: string;\r\n }\r\n ): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}/metadata`, {\r\n method: 'PUT',\r\n body: metadata,\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Burn NFT (single)\r\n */\r\n async burnNft(tokenId: string): Promise<any> {\r\n const response = await this.apiCall(`/v1/nfts/${tokenId}`, {\r\n method: 'DELETE',\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Batch burn NFTs\r\n */\r\n async batchBurnNfts(tokenIds: string[]): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/burn/batch', {\r\n method: 'POST',\r\n body: { tokenIds },\r\n });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Pack opener - mint random NFTs from a drop table\r\n */\r\n async packOpener(params: {\r\n dropTableId: string;\r\n recipientAddress: string;\r\n }): Promise<any> {\r\n const response = await this.apiCall('/v1/nfts/pack-opener', {\r\n method: 'POST',\r\n body: params,\r\n });\r\n return response.json();\r\n }\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omen.foundation/game-sdk",
3
- "version": "1.0.13",
3
+ "version": "1.0.14",
4
4
  "description": "OmenX Game SDK for web applications - OAuth authentication and API integration",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",