@civic/auth 0.9.6-beta.1 → 0.10.0-beta.0

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.
Files changed (223) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/dist/nextjs/actions.d.ts +12 -0
  3. package/dist/nextjs/actions.d.ts.map +1 -0
  4. package/dist/nextjs/actions.js +26 -0
  5. package/dist/nextjs/actions.js.map +1 -0
  6. package/dist/nextjs/config.d.ts +2 -0
  7. package/dist/nextjs/config.d.ts.map +1 -1
  8. package/dist/nextjs/config.js +3 -2
  9. package/dist/nextjs/config.js.map +1 -1
  10. package/dist/nextjs/cookies.d.ts.map +1 -1
  11. package/dist/nextjs/cookies.js +45 -3
  12. package/dist/nextjs/cookies.js.map +1 -1
  13. package/dist/nextjs/hooks/useInitialAuthConfig.d.ts +31 -0
  14. package/dist/nextjs/hooks/useInitialAuthConfig.d.ts.map +1 -0
  15. package/dist/nextjs/hooks/useInitialAuthConfig.js +113 -0
  16. package/dist/nextjs/hooks/useInitialAuthConfig.js.map +1 -0
  17. package/dist/nextjs/index.d.ts +1 -0
  18. package/dist/nextjs/index.d.ts.map +1 -1
  19. package/dist/nextjs/index.js +13 -3
  20. package/dist/nextjs/index.js.map +1 -1
  21. package/dist/nextjs/providers/NextAuthProvider.d.ts +6 -7
  22. package/dist/nextjs/providers/NextAuthProvider.d.ts.map +1 -1
  23. package/dist/nextjs/providers/NextAuthProvider.js +19 -138
  24. package/dist/nextjs/providers/NextAuthProvider.js.map +1 -1
  25. package/dist/nextjs/providers/NextAuthProviderClient.d.ts +11 -0
  26. package/dist/nextjs/providers/NextAuthProviderClient.d.ts.map +1 -0
  27. package/dist/nextjs/providers/NextAuthProviderClient.js +62 -0
  28. package/dist/nextjs/providers/NextAuthProviderClient.js.map +1 -0
  29. package/dist/nextjs/providers/ServerUserContext.d.ts +2 -0
  30. package/dist/nextjs/providers/ServerUserContext.d.ts.map +1 -0
  31. package/dist/nextjs/providers/ServerUserContext.js +5 -0
  32. package/dist/nextjs/providers/ServerUserContext.js.map +1 -0
  33. package/dist/nextjs/routeHandler.d.ts.map +1 -1
  34. package/dist/nextjs/routeHandler.js +240 -341
  35. package/dist/nextjs/routeHandler.js.map +1 -1
  36. package/dist/react-router-7/components/UserButton.js +1 -1
  37. package/dist/react-router-7/components/UserButton.js.map +1 -1
  38. package/dist/react-router-7/routeHandler.d.ts.map +1 -1
  39. package/dist/react-router-7/routeHandler.js +1 -0
  40. package/dist/react-router-7/routeHandler.js.map +1 -1
  41. package/dist/react-router-7/useUser.d.ts.map +1 -1
  42. package/dist/react-router-7/useUser.js +13 -2
  43. package/dist/react-router-7/useUser.js.map +1 -1
  44. package/dist/reactjs/components/ButtonContentOrLoader.d.ts.map +1 -1
  45. package/dist/reactjs/components/ButtonContentOrLoader.js +1 -3
  46. package/dist/reactjs/components/ButtonContentOrLoader.js.map +1 -1
  47. package/dist/reactjs/components/CivicAuthIframeContainer.d.ts +2 -0
  48. package/dist/reactjs/components/CivicAuthIframeContainer.d.ts.map +1 -0
  49. package/dist/reactjs/components/CivicAuthIframeContainer.js +26 -0
  50. package/dist/reactjs/components/CivicAuthIframeContainer.js.map +1 -0
  51. package/dist/reactjs/components/SignInButton.d.ts.map +1 -1
  52. package/dist/reactjs/components/SignInButton.js +11 -1
  53. package/dist/reactjs/components/SignInButton.js.map +1 -1
  54. package/dist/reactjs/components/UserButton.d.ts +9 -2
  55. package/dist/reactjs/components/UserButton.d.ts.map +1 -1
  56. package/dist/reactjs/components/UserButton.js +41 -9
  57. package/dist/reactjs/components/UserButton.js.map +1 -1
  58. package/dist/reactjs/components/index.d.ts +1 -0
  59. package/dist/reactjs/components/index.d.ts.map +1 -1
  60. package/dist/reactjs/components/index.js +1 -0
  61. package/dist/reactjs/components/index.js.map +1 -1
  62. package/dist/reactjs/core/GlobalAuthManager.d.ts +26 -0
  63. package/dist/reactjs/core/GlobalAuthManager.d.ts.map +1 -1
  64. package/dist/reactjs/core/GlobalAuthManager.js +76 -5
  65. package/dist/reactjs/core/GlobalAuthManager.js.map +1 -1
  66. package/dist/reactjs/hooks/useUser.d.ts +19 -2
  67. package/dist/reactjs/hooks/useUser.d.ts.map +1 -1
  68. package/dist/reactjs/hooks/useUser.js +95 -7
  69. package/dist/reactjs/hooks/useUser.js.map +1 -1
  70. package/dist/reactjs/index.d.ts +1 -2
  71. package/dist/reactjs/index.d.ts.map +1 -1
  72. package/dist/reactjs/index.js +1 -2
  73. package/dist/reactjs/index.js.map +1 -1
  74. package/dist/server/ServerAuthenticationResolver.d.ts.map +1 -1
  75. package/dist/server/ServerAuthenticationResolver.js +18 -0
  76. package/dist/server/ServerAuthenticationResolver.js.map +1 -1
  77. package/dist/server/index.d.ts +1 -1
  78. package/dist/server/index.d.ts.map +1 -1
  79. package/dist/server/index.js.map +1 -1
  80. package/dist/server/logout.d.ts.map +1 -1
  81. package/dist/server/logout.js +11 -2
  82. package/dist/server/logout.js.map +1 -1
  83. package/dist/server/session.d.ts +51 -0
  84. package/dist/server/session.d.ts.map +1 -1
  85. package/dist/server/session.js +296 -17
  86. package/dist/server/session.js.map +1 -1
  87. package/dist/shared/components/SVGLoading.js +1 -1
  88. package/dist/shared/components/SVGLoading.js.map +1 -1
  89. package/dist/shared/components/UserButtonPresentation.d.ts.map +1 -0
  90. package/dist/shared/components/UserButtonPresentation.js.map +1 -0
  91. package/dist/shared/hooks/index.d.ts +1 -2
  92. package/dist/shared/hooks/index.d.ts.map +1 -1
  93. package/dist/shared/hooks/index.js +1 -2
  94. package/dist/shared/hooks/index.js.map +1 -1
  95. package/dist/shared/hooks/useBfcacheHandler.d.ts +23 -0
  96. package/dist/shared/hooks/useBfcacheHandler.d.ts.map +1 -0
  97. package/dist/shared/hooks/useBfcacheHandler.js +65 -0
  98. package/dist/shared/hooks/useBfcacheHandler.js.map +1 -0
  99. package/dist/shared/index.d.ts +1 -0
  100. package/dist/shared/index.d.ts.map +1 -1
  101. package/dist/shared/index.js +1 -0
  102. package/dist/shared/index.js.map +1 -1
  103. package/dist/shared/lib/util.d.ts +32 -0
  104. package/dist/shared/lib/util.d.ts.map +1 -1
  105. package/dist/shared/lib/util.js +79 -0
  106. package/dist/shared/lib/util.js.map +1 -1
  107. package/dist/shared/providers/AuthStatusContext.d.ts.map +1 -1
  108. package/dist/shared/providers/AuthStatusContext.js +2 -1
  109. package/dist/shared/providers/AuthStatusContext.js.map +1 -1
  110. package/dist/shared/providers/CivicAuthConfigContext.d.ts +2 -1
  111. package/dist/shared/providers/CivicAuthConfigContext.d.ts.map +1 -1
  112. package/dist/shared/providers/CivicAuthConfigContext.js +5 -2
  113. package/dist/shared/providers/CivicAuthConfigContext.js.map +1 -1
  114. package/dist/shared/providers/types.d.ts +1 -0
  115. package/dist/shared/providers/types.d.ts.map +1 -1
  116. package/dist/shared/providers/types.js.map +1 -1
  117. package/dist/shared/utils/locationChange.d.ts +34 -0
  118. package/dist/shared/utils/locationChange.d.ts.map +1 -0
  119. package/dist/shared/utils/locationChange.js +28 -0
  120. package/dist/shared/utils/locationChange.js.map +1 -0
  121. package/dist/shared/version.d.ts +1 -1
  122. package/dist/shared/version.d.ts.map +1 -1
  123. package/dist/shared/version.js +1 -1
  124. package/dist/shared/version.js.map +1 -1
  125. package/dist/vanillajs/auth/AuthenticationEvents.d.ts +10 -1
  126. package/dist/vanillajs/auth/AuthenticationEvents.d.ts.map +1 -1
  127. package/dist/vanillajs/auth/AuthenticationEvents.js +29 -0
  128. package/dist/vanillajs/auth/AuthenticationEvents.js.map +1 -1
  129. package/dist/vanillajs/auth/BackendAuthenticationRefresher.d.ts.map +1 -1
  130. package/dist/vanillajs/auth/BackendAuthenticationRefresher.js +2 -2
  131. package/dist/vanillajs/auth/BackendAuthenticationRefresher.js.map +1 -1
  132. package/dist/vanillajs/auth/CivicAuth.d.ts +32 -0
  133. package/dist/vanillajs/auth/CivicAuth.d.ts.map +1 -1
  134. package/dist/vanillajs/auth/CivicAuth.js +270 -55
  135. package/dist/vanillajs/auth/CivicAuth.js.map +1 -1
  136. package/dist/vanillajs/auth/SessionManager.d.ts +3 -2
  137. package/dist/vanillajs/auth/SessionManager.d.ts.map +1 -1
  138. package/dist/vanillajs/auth/SessionManager.js +33 -7
  139. package/dist/vanillajs/auth/SessionManager.js.map +1 -1
  140. package/dist/vanillajs/auth/config/ConfigProcessor.d.ts.map +1 -1
  141. package/dist/vanillajs/auth/config/ConfigProcessor.js +2 -14
  142. package/dist/vanillajs/auth/config/ConfigProcessor.js.map +1 -1
  143. package/dist/vanillajs/auth/handlers/IframeAuthHandler.d.ts.map +1 -1
  144. package/dist/vanillajs/auth/handlers/IframeAuthHandler.js +64 -11
  145. package/dist/vanillajs/auth/handlers/IframeAuthHandler.js.map +1 -1
  146. package/dist/vanillajs/auth/handlers/MessageHandler.d.ts.map +1 -1
  147. package/dist/vanillajs/auth/handlers/MessageHandler.js +4 -1
  148. package/dist/vanillajs/auth/handlers/MessageHandler.js.map +1 -1
  149. package/dist/vanillajs/auth/handlers/PopupHandler.d.ts.map +1 -1
  150. package/dist/vanillajs/auth/handlers/PopupHandler.js +3 -1
  151. package/dist/vanillajs/auth/handlers/PopupHandler.js.map +1 -1
  152. package/dist/vanillajs/auth/types/AuthTypes.d.ts +11 -1
  153. package/dist/vanillajs/auth/types/AuthTypes.d.ts.map +1 -1
  154. package/dist/vanillajs/auth/types/AuthTypes.js.map +1 -1
  155. package/dist/vanillajs/iframe/IframeManager.d.ts +22 -1
  156. package/dist/vanillajs/iframe/IframeManager.d.ts.map +1 -1
  157. package/dist/vanillajs/iframe/IframeManager.js +184 -22
  158. package/dist/vanillajs/iframe/IframeManager.js.map +1 -1
  159. package/dist/vanillajs/types/index.d.ts +1 -1
  160. package/dist/vanillajs/types/index.d.ts.map +1 -1
  161. package/dist/vanillajs/types/index.js +1 -1
  162. package/dist/vanillajs/types/index.js.map +1 -1
  163. package/dist/vanillajs/ui/LoadingComponents.d.ts +4 -0
  164. package/dist/vanillajs/ui/LoadingComponents.d.ts.map +1 -1
  165. package/dist/vanillajs/ui/LoadingComponents.js +51 -1
  166. package/dist/vanillajs/ui/LoadingComponents.js.map +1 -1
  167. package/package.json +3 -3
  168. package/dist/nextjs/hooks/index.d.ts +0 -2
  169. package/dist/nextjs/hooks/index.d.ts.map +0 -1
  170. package/dist/nextjs/hooks/index.js +0 -2
  171. package/dist/nextjs/hooks/index.js.map +0 -1
  172. package/dist/nextjs/hooks/usePrevious.d.ts +0 -2
  173. package/dist/nextjs/hooks/usePrevious.d.ts.map +0 -1
  174. package/dist/nextjs/hooks/usePrevious.js +0 -9
  175. package/dist/nextjs/hooks/usePrevious.js.map +0 -1
  176. package/dist/nextjs/hooks/useUserCookie.d.ts +0 -9
  177. package/dist/nextjs/hooks/useUserCookie.d.ts.map +0 -1
  178. package/dist/nextjs/hooks/useUserCookie.js +0 -109
  179. package/dist/nextjs/hooks/useUserCookie.js.map +0 -1
  180. package/dist/react-router-7/components/UserButtonPresentation.d.ts.map +0 -1
  181. package/dist/react-router-7/components/UserButtonPresentation.js.map +0 -1
  182. package/dist/shared/components/BlockDisplay.d.ts +0 -6
  183. package/dist/shared/components/BlockDisplay.d.ts.map +0 -1
  184. package/dist/shared/components/BlockDisplay.js +0 -30
  185. package/dist/shared/components/BlockDisplay.js.map +0 -1
  186. package/dist/shared/components/CivicAuthIframe.d.ts +0 -10
  187. package/dist/shared/components/CivicAuthIframe.d.ts.map +0 -1
  188. package/dist/shared/components/CivicAuthIframe.js +0 -49
  189. package/dist/shared/components/CivicAuthIframe.js.map +0 -1
  190. package/dist/shared/components/CivicAuthIframeContainer.d.ts +0 -15
  191. package/dist/shared/components/CivicAuthIframeContainer.d.ts.map +0 -1
  192. package/dist/shared/components/CivicAuthIframeContainer.js +0 -177
  193. package/dist/shared/components/CivicAuthIframeContainer.js.map +0 -1
  194. package/dist/shared/components/CivicAuthLogoutIframeContainer.d.ts +0 -6
  195. package/dist/shared/components/CivicAuthLogoutIframeContainer.d.ts.map +0 -1
  196. package/dist/shared/components/CivicAuthLogoutIframeContainer.js +0 -51
  197. package/dist/shared/components/CivicAuthLogoutIframeContainer.js.map +0 -1
  198. package/dist/shared/components/IFrameAndLoading.d.ts +0 -7
  199. package/dist/shared/components/IFrameAndLoading.d.ts.map +0 -1
  200. package/dist/shared/components/IFrameAndLoading.js +0 -66
  201. package/dist/shared/components/IFrameAndLoading.js.map +0 -1
  202. package/dist/shared/hooks/useAuth.d.ts +0 -3
  203. package/dist/shared/hooks/useAuth.d.ts.map +0 -1
  204. package/dist/shared/hooks/useAuth.js +0 -12
  205. package/dist/shared/hooks/useAuth.js.map +0 -1
  206. package/dist/shared/hooks/useIframe.d.ts +0 -3
  207. package/dist/shared/hooks/useIframe.d.ts.map +0 -1
  208. package/dist/shared/hooks/useIframe.js +0 -13
  209. package/dist/shared/hooks/useIframe.js.map +0 -1
  210. package/dist/shared/hooks/useIsInIframe.d.ts +0 -7
  211. package/dist/shared/hooks/useIsInIframe.d.ts.map +0 -1
  212. package/dist/shared/hooks/useIsInIframe.js +0 -23
  213. package/dist/shared/hooks/useIsInIframe.js.map +0 -1
  214. package/dist/shared/hooks/useSignIn.d.ts +0 -20
  215. package/dist/shared/hooks/useSignIn.d.ts.map +0 -1
  216. package/dist/shared/hooks/useSignIn.js +0 -358
  217. package/dist/shared/hooks/useSignIn.js.map +0 -1
  218. package/dist/shared/providers/IframeProvider.d.ts +0 -28
  219. package/dist/shared/providers/IframeProvider.d.ts.map +0 -1
  220. package/dist/shared/providers/IframeProvider.js +0 -64
  221. package/dist/shared/providers/IframeProvider.js.map +0 -1
  222. /package/dist/{react-router-7 → shared}/components/UserButtonPresentation.d.ts +0 -0
  223. /package/dist/{react-router-7 → shared}/components/UserButtonPresentation.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"IframeAuthHandler.js","sourceRoot":"","sources":["../../../../src/vanillajs/auth/handlers/IframeAuthHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { AuthEvent } from \"../../types/index.js\";\nimport type { AuthResult } from \"../../types/index.js\";\nimport type { ProcessedCivicAuthConfig } from \"../types/AuthTypes.js\";\nimport { CivicAuthError, CivicAuthErrorCode } from \"../types/AuthTypes.js\";\nimport { SignalObserver } from \"../../iframe/SignalObserver.js\";\nimport { IframeManager } from \"../../iframe/IframeManager.js\";\nimport type { createLogger } from \"../../utils/logger.js\";\nimport { createLogger as createLoggerFn } from \"../../utils/logger.js\";\nimport { WAIT_FOR_LOGIN_APP_BROWSER_DETECTION_TIMEOUT } from \"@/constants.js\";\n\nexport interface IframeAuthHandlerConfig {\n config: ProcessedCivicAuthConfig;\n logger: ReturnType<typeof createLogger>;\n onAuthSuccess: (result: AuthResult) => void;\n onAuthError: (error: Error) => void;\n cleanup: () => void;\n messageHandler: (event: MessageEvent) => void;\n}\n\nexport class IframeAuthHandler {\n private config: ProcessedCivicAuthConfig;\n private logger = createLoggerFn(\"iframe-auth\");\n private onAuthSuccess: (result: AuthResult) => void;\n private onAuthError: (error: Error) => void;\n private cleanup: () => void;\n private messageHandler: (event: MessageEvent) => void;\n private iframeManager?: IframeManager;\n private iframeElement?: HTMLIFrameElement;\n private signalObserver?: SignalObserver;\n private earlyAuthSuccessHandler: (event: CustomEvent) => void;\n private isPreloadEnabled: boolean; // Initialized from config\n\n constructor(handlerConfig: IframeAuthHandlerConfig) {\n this.config = handlerConfig.config;\n this.logger = handlerConfig.logger;\n this.onAuthSuccess = handlerConfig.onAuthSuccess;\n this.onAuthError = handlerConfig.onAuthError;\n this.cleanup = handlerConfig.cleanup;\n this.messageHandler = handlerConfig.messageHandler;\n\n // Set preload enabled state from config\n this.isPreloadEnabled = this.config.preloadIframe;\n\n // Listen for early auth success signals from login-app\n this.earlyAuthSuccessHandler = (event: CustomEvent) => {\n this.logger.info(\"Received early auth success signal from login-app\", {\n detail: event.detail,\n });\n\n // Close the modal immediately but keep iframe for callback processing\n if (this.iframeManager) {\n this.logger.info(\"Closing modal early due to auth success signal\");\n this.iframeManager.hide();\n\n // Emit event to notify that modal is closing early\n this.config.events?.emit(AuthEvent.SIGN_IN_STARTED, {\n detail: \"Modal closed early due to auth success signal\",\n });\n }\n };\n\n window.addEventListener(\n \"civic-auth-success-early\",\n this.earlyAuthSuccessHandler as EventListener,\n );\n }\n\n /**\n * Preloads the iframe with the authentication URL for instant display later\n * This creates the iframe in the background but keeps it completely hidden\n */\n public async preloadIframe(fullAuthUrl: string): Promise<void> {\n if (!this.isPreloadEnabled) {\n this.logger.debug(\"Iframe preloading is disabled, skipping preload\");\n return;\n }\n\n this.logger.debug(\"Preloading iframe for instant sign-in\", {\n url: fullAuthUrl,\n });\n\n // Determine the actual display mode for IframeManager first\n const iframeDisplayMode = this.determineIframeDisplayMode();\n\n let container = this.getContainerElement();\n\n // For modal mode, if no container is provided, create one dynamically\n if (iframeDisplayMode === \"modal\" && !container) {\n container = this.createModalContainer();\n }\n\n if (!container) {\n const error = new CivicAuthError(\n \"Target container element not found for preloading.\",\n CivicAuthErrorCode.CONTAINER_NOT_FOUND,\n );\n this.logger.error(error.message);\n throw error;\n }\n\n this.logger.debug(\"Creating IframeManager for preloading\", {\n url: fullAuthUrl,\n containerId: container?.id,\n iframeId: this.config.iframeId,\n origin: window.location.origin,\n iframeDisplayMode,\n });\n\n // Create IframeManager with appropriate display mode\n this.iframeManager = new IframeManager({\n container: container,\n displayMode: iframeDisplayMode,\n iframeId: this.config.iframeId,\n onClose: () => {\n this.logger.debug(\"Authentication close requested during preload\");\n // For preload, we don't want to trigger auth error, just cleanup\n this.cleanupIframe();\n },\n });\n\n // Preload the iframe using IframeManager\n this.iframeElement = this.iframeManager.preloadIframe(fullAuthUrl);\n\n // Set up event handlers for the preloaded iframe\n this.setupIframeEventHandlers();\n this.setupIframeNavigationMonitoring();\n\n this.logger.debug(\"Iframe preloaded successfully\", { url: fullAuthUrl });\n }\n\n public async handleIframeAuth(\n fullAuthUrl: string,\n ): Promise<HTMLIFrameElement> {\n // Check if we have a preloaded iframe that we can show instantly\n // We use the preloaded iframe if available, even if URLs don't exactly match,\n // since PKCE challenges and other parameters may differ between preload and actual auth\n if (this.iframeManager?.isIframePreloaded() && this.iframeElement) {\n const preloadedUrl = this.iframeManager.getPreloadedUrl();\n this.logger.debug(\"Using preloaded iframe for instant sign-in\", {\n preloadedUrl,\n requestedUrl: fullAuthUrl,\n urlsMatch: preloadedUrl === fullAuthUrl,\n });\n\n // Don't change iframe.src for preloaded iframes - use them as-is to avoid reload\n // The preloaded authentication flow will work perfectly without URL changes\n this.logger.debug(\"Using preloaded iframe without reload\", {\n preloadedUrl,\n requestedUrl: fullAuthUrl,\n action: \"skipping_url_change_to_prevent_reload\",\n });\n\n // Update the onClose handler for active authentication\n // During preload, onClose only cleaned up, but during active auth it should emit error events\n this.iframeManager.updateOnCloseHandler(() => {\n this.logger.debug(\n \"Authentication close requested by user (backdrop click, close button, or Escape key)\",\n );\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Authentication cancelled by user\",\n });\n\n const error = new CivicAuthError(\n \"Authentication cancelled by user\",\n CivicAuthErrorCode.USER_CANCELLED,\n );\n\n this.onAuthError(error);\n this.cleanup();\n });\n\n // Show the preloaded iframe instantly\n this.iframeElement = this.iframeManager.createIframe(fullAuthUrl);\n\n this.config.events?.emit(AuthEvent.SIGN_IN_STARTED, {\n detail: \"Preloaded iframe displayed instantly\",\n });\n\n return this.iframeElement;\n }\n\n // Fallback to creating a new iframe if no preload is available\n this.logger.debug(\"No preloaded iframe available, creating new iframe\", {\n url: fullAuthUrl,\n });\n\n // Determine the actual display mode for IframeManager first\n const iframeDisplayMode = this.determineIframeDisplayMode();\n\n let container = this.getContainerElement();\n\n // For modal mode, if no container is provided, create one dynamically\n if (iframeDisplayMode === \"modal\" && !container) {\n container = this.createModalContainer();\n }\n\n if (!container) {\n const error = new CivicAuthError(\n \"Target container element not found.\",\n CivicAuthErrorCode.CONTAINER_NOT_FOUND,\n );\n this.logger.error(error.message);\n throw error;\n }\n\n this.logger.debug(\"Creating iframe with modal backdrop\", {\n url: fullAuthUrl,\n containerId: container?.id,\n iframeId: this.config.iframeId,\n origin: window.location.origin,\n iframeDisplayMode,\n containerCreated:\n iframeDisplayMode === \"modal\" && !this.config.targetContainerElement,\n });\n\n this.logger.debug(\n `🎯 CivicAuth: Creating IframeManager with display mode: ${iframeDisplayMode}`,\n );\n\n // Create IframeManager with appropriate display mode\n this.iframeManager = new IframeManager({\n container: container,\n displayMode: iframeDisplayMode,\n iframeId: this.config.iframeId,\n /**\n * Handles iframe closure events initiated by the user.\n * This includes backdrop clicks, close button clicks, or Escape key presses.\n * Emits an error event and cleans up the authentication process.\n */\n onClose: () => {\n this.logger.debug(\n \"Authentication close requested by user (backdrop click, close button, or Escape key)\",\n );\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Authentication cancelled by user\",\n });\n\n const error = new CivicAuthError(\n \"Authentication cancelled by user\",\n CivicAuthErrorCode.USER_CANCELLED,\n );\n\n this.onAuthError(error);\n this.cleanup();\n },\n });\n\n // Create the iframe using IframeManager\n this.iframeElement = this.iframeManager.createIframe(fullAuthUrl);\n\n this.config.events?.emit(AuthEvent.SIGN_IN_STARTED, {\n detail: \"Iframe created with modal backdrop\",\n });\n\n this.setupIframeEventHandlers();\n this.setupIframeNavigationMonitoring();\n\n return this.iframeElement;\n }\n\n public getIframeManager(): IframeManager | undefined {\n return this.iframeManager;\n }\n\n public getIframeElement(): HTMLIFrameElement | undefined {\n return this.iframeElement;\n }\n\n public cleanupIframe(): void {\n this.logger.debug(\"Cleaning up iframe manager\");\n this.iframeManager?.cleanup();\n this.iframeManager = undefined;\n\n if (this.iframeElement) {\n this.iframeElement = undefined;\n }\n\n // Remove early auth success event listener\n if (this.earlyAuthSuccessHandler) {\n window.removeEventListener(\n \"civic-auth-success-early\",\n this.earlyAuthSuccessHandler as EventListener,\n );\n }\n\n // Clean up dynamically created modal containers\n this.cleanupDynamicModalContainer();\n }\n\n private cleanupDynamicModalContainer(): void {\n // Only clean up containers we created dynamically (not user-provided ones)\n if (!this.config.targetContainerElement) {\n const dynamicContainer = document.querySelector(\n `[data-civic-auth-modal=\"true\"]#${this.config.iframeId}-modal-container`,\n );\n\n if (dynamicContainer && dynamicContainer.parentNode) {\n this.logger.debug(\"Removing dynamic modal container\", {\n containerId: dynamicContainer.id,\n });\n dynamicContainer.parentNode.removeChild(dynamicContainer);\n }\n }\n }\n\n private createModalContainer(): HTMLElement {\n const container = document.createElement(\"div\");\n container.id = `${this.config.iframeId}-modal-container`;\n container.setAttribute(\"data-civic-auth-modal\", \"true\");\n\n // Append to body for modal overlay\n document.body.appendChild(container);\n\n this.logger.debug(\"Created dynamic modal container\", {\n containerId: container.id,\n });\n\n return container;\n }\n\n private getContainerElement(): HTMLElement | null {\n if (!this.config.targetContainerElement) {\n return null;\n }\n\n if (typeof this.config.targetContainerElement === \"string\") {\n const element = document.getElementById(\n this.config.targetContainerElement,\n );\n if (!element) {\n this.logger.warn(\n `Container element with ID \"${this.config.targetContainerElement}\" not found`,\n );\n }\n return element;\n }\n return this.config.targetContainerElement;\n }\n\n private determineIframeDisplayMode(): \"modal\" | \"embedded\" {\n // Priority 1: Explicit iframeDisplayMode setting from config\n // This is the most specific instruction for how the iframe itself should be styled.\n if (this.config.iframeDisplayMode) {\n this.logger.debug(\n `Using configured iframeDisplayMode: ${this.config.iframeDisplayMode}`,\n );\n return this.config.iframeDisplayMode;\n }\n\n // Priority 2: If iframeDisplayMode is NOT set, and the overall displayMode is \"iframe\",\n // default the iframe's own rendering style to \"modal\" (user-friendly default).\n // To get an embedded iframe, iframeDisplayMode: \"embedded\" should be set explicitly.\n if (this.config.displayMode === \"iframe\") {\n this.logger.debug(\n \"Overall displayMode is 'iframe' and iframeDisplayMode is not set, defaulting iframe style to 'modal'.\",\n );\n return \"modal\";\n }\n\n // Fallback for unexpected scenarios or if IframeAuthHandler is invoked with other displayModes.\n this.logger.warn(\n `determineIframeDisplayMode called with overall displayMode: '${this.config.displayMode}' ` +\n `and no explicit iframeDisplayMode. Defaulting iframe style to 'modal'.`,\n );\n return \"modal\";\n }\n\n private setupIframeEventHandlers(): void {\n if (!this.iframeElement) return;\n\n this.iframeElement.onload = () => {\n this.logger.info(\"Iframe loaded\", {\n iframeSrc: this.iframeElement?.src,\n currentOrigin: window.location.origin,\n expectedAuthServerOrigin: new URL(this.config.oauthServerBaseUrl)\n .origin,\n });\n\n if (!this.iframeElement?.contentWindow) {\n const errorMsg = \"Iframe content window not available after load.\";\n this.logger.error(errorMsg, {\n iframeSrc: this.iframeElement?.src,\n });\n\n const error = new Error(errorMsg);\n this.onAuthError(error);\n this.cleanup();\n return;\n }\n\n // Set up postMessage listener for cross-origin communication\n window.addEventListener(\"message\", this.messageHandler);\n this.logger.info(\n \"Added cross-origin message event listener for auth server communication\",\n {\n parentOrigin: window.location.origin,\n authServerOrigin: new URL(this.config.oauthServerBaseUrl).origin,\n },\n );\n\n // Hide iframe content if it's not the login app\n this.checkAndHideNonLoginContent();\n\n // Try to detect redirect to our domain\n this.checkIframeRedirect();\n };\n\n this.iframeElement.onerror = (event) => {\n this.logger.error(\"Iframe load error\", {\n event,\n iframeSrc: this.iframeElement?.src,\n currentOrigin: window.location.origin,\n });\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Iframe load error\",\n error: event,\n });\n\n const error = new Error(\"Iframe failed to load.\");\n this.onAuthError(error);\n this.cleanup();\n };\n }\n\n private checkAndHideNonLoginContent(): void {\n try {\n const currentUrl = this.iframeElement?.contentWindow?.location.href;\n if (currentUrl) {\n const currentOrigin = new URL(currentUrl).origin;\n const expectedAuthServerOrigin = this.config.oauthServerBaseUrl\n ? new URL(this.config.oauthServerBaseUrl).origin\n : null;\n const isOnAuthServer = expectedAuthServerOrigin\n ? currentOrigin === expectedAuthServerOrigin\n : false;\n const isCallbackUrl = this.config.redirectUrl\n ? currentUrl.startsWith(this.config.redirectUrl)\n : false;\n\n if (isOnAuthServer && !isCallbackUrl) {\n this.logger.info(\n \"👀 Showing iframe content - confirmed login app on auth server origin\",\n {\n currentUrl,\n isOnAuthServer,\n isCallbackUrl,\n currentOrigin,\n expectedAuthServerOrigin,\n },\n );\n this.iframeManager?.forceHideLoader();\n } else {\n this.logger.info(\n \"🙈 Hiding iframe completely - not login app or on callback URL\",\n {\n currentUrl,\n isOnAuthServer,\n isCallbackUrl,\n currentOrigin,\n expectedAuthServerOrigin,\n reason: !isOnAuthServer\n ? expectedAuthServerOrigin\n ? \"not on auth server (origin mismatch)\"\n : \"auth server origin unknown\"\n : \"on callback URL (or origin mismatch for login page)\",\n },\n );\n\n if (isCallbackUrl) {\n this.iframeManager?.hide();\n } else {\n this.iframeManager?.forceShowLoader();\n }\n }\n }\n } catch (error) {\n this.logger.debug(\n \"Cannot access iframe URL (likely cross-origin) - assuming login app, showing content.\",\n { error: error instanceof Error ? error.message : String(error) },\n );\n setTimeout(() => {\n // Force hide loader after a short delay to ensure any initial loading is complete\n // to give the login-app time to send any post message signals\n this.iframeManager?.forceHideLoader();\n }, WAIT_FOR_LOGIN_APP_BROWSER_DETECTION_TIMEOUT);\n }\n }\n\n private checkIframeRedirect(): void {\n try {\n const currentIframeHref =\n this.iframeElement?.contentWindow?.location.href;\n\n if (currentIframeHref) {\n this.logger.debug(\"Iframe current href accessible\", {\n href: currentIframeHref,\n redirectUrl: this.config.redirectUrl,\n startsWithRedirect: currentIframeHref.startsWith(\n this.config.redirectUrl,\n ),\n });\n\n if (currentIframeHref.startsWith(this.config.redirectUrl)) {\n this.logger.info(\n \"Iframe has navigated to redirectUrl (same-origin). Setting up DOM observer.\",\n );\n\n // Hide content since we're on callback page now\n this.checkAndHideNonLoginContent();\n\n // Set up signal observer for same-origin callback page\n if (\n this.iframeElement?.contentDocument &&\n this.iframeElement.contentDocument.body\n ) {\n this.setupSignalObserver(this.iframeElement.contentDocument);\n } else {\n this.logger.warn(\n \"Iframe content document or body not available for signal observer\",\n );\n }\n }\n }\n } catch (error) {\n this.logger.debug(\n \"Error checking iframe href (expected for cross-origin)\",\n {\n error: error instanceof Error ? error.message : String(error),\n iframeSrc: this.iframeElement?.src,\n },\n );\n // This is expected when the iframe is on the auth server domain\n this.logger.info(\n \"Iframe is on auth server domain - using postMessage for communication\",\n {\n parentOrigin: window.location.origin,\n authServerOrigin: new URL(this.config.oauthServerBaseUrl).origin,\n },\n );\n }\n }\n\n private setupSignalObserver(iframeDoc: Document): void {\n const signalObserver = new SignalObserver(\n {\n textSignals: this.config.textSignals,\n events: this.config.events,\n logger: this.logger,\n },\n this.onAuthSuccess,\n (error?: Error) =>\n this.onAuthError(error || new Error(\"Signal observer error\")),\n () => this.cleanup(),\n );\n\n signalObserver.setup(iframeDoc);\n }\n\n private setupIframeNavigationMonitoring(): void {\n // Monitor iframe navigation to detect when it redirects to our callback URL\n let monitoringInterval: number | undefined = undefined;\n let lastKnownUrl = \"\";\n\n const checkIframeNavigation = () => {\n if (!this.iframeElement?.contentWindow) {\n if (monitoringInterval) {\n clearInterval(monitoringInterval);\n }\n return;\n }\n\n try {\n const currentUrl = this.iframeElement.contentWindow.location.href;\n\n if (currentUrl !== lastKnownUrl) {\n lastKnownUrl = currentUrl;\n this.logger.debug(\"Iframe navigation detected\", {\n newUrl: currentUrl,\n redirectUrl: this.config.redirectUrl,\n isCallbackUrl: currentUrl.startsWith(this.config.redirectUrl),\n });\n\n // Check if iframe has navigated to our callback URL\n if (currentUrl.startsWith(this.config.redirectUrl)) {\n // Hide immediately on callback URL detection\n this.iframeManager?.hide();\n this.logger.info(\n \"Iframe navigated to callback URL - setting up signal observer\",\n );\n\n if (monitoringInterval) {\n clearInterval(monitoringInterval);\n }\n\n // Set up signal observer for same-origin callback page\n if (\n this.iframeElement.contentDocument &&\n this.iframeElement.contentDocument.body\n ) {\n this.setupSignalObserver(this.iframeElement.contentDocument);\n }\n\n // Also check for URL parameters (code, error) in case of direct callback\n this.processCallbackUrl(currentUrl);\n } else {\n // Hide content if not on login app\n this.checkAndHideNonLoginContent();\n }\n }\n } catch {\n // Expected when iframe is on different origin\n // Only log if we haven't seen this before\n if (lastKnownUrl !== \"cross-origin\") {\n lastKnownUrl = \"cross-origin\";\n this.logger.debug(\n \"Iframe on cross-origin domain (expected during auth flow)\",\n );\n }\n }\n };\n\n // Check immediately and then every 100ms for faster detection\n checkIframeNavigation();\n monitoringInterval = window.setInterval(checkIframeNavigation, 100);\n\n // Store cleanup function to clear monitoring\n const originalCleanup = this.cleanup;\n this.cleanup = () => {\n if (monitoringInterval) {\n clearInterval(monitoringInterval);\n }\n originalCleanup();\n };\n }\n\n private processCallbackUrl(currentUrl: string): void {\n const urlParams = new URLSearchParams(new URL(currentUrl).search);\n const code = urlParams.get(\"code\");\n const error = urlParams.get(\"error\");\n\n if (code) {\n this.logger.info(\"Authorization code detected in iframe URL\", {\n code: code.substring(0, 10) + \"...\",\n hasState: !!urlParams.get(\"state\"),\n });\n }\n\n if (error) {\n this.logger.error(\"OAuth error detected in iframe URL\", {\n error,\n errorDescription: urlParams.get(\"error_description\"),\n });\n\n const authError = new CivicAuthError(\n `OAuth error: ${error}`,\n CivicAuthErrorCode.INVALID_MESSAGE,\n );\n\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: authError.message,\n error: urlParams.get(\"error_description\") || error,\n });\n\n this.onAuthError(authError);\n }\n }\n\n public navigateIframe(url: string): void {\n if (!this.iframeElement) {\n this.logger.error(\n \"Cannot navigate iframe, iframeElement is not available.\",\n );\n this.onAuthError(\n new CivicAuthError(\n \"Iframe element not found for navigation.\",\n CivicAuthErrorCode.IFRAME_NOT_FOUND,\n ),\n );\n return;\n }\n if (!this.iframeManager) {\n this.logger.error(\n \"Cannot navigate iframe, iframeManager is not available.\",\n );\n this.onAuthError(\n new CivicAuthError(\n \"Iframe manager not found for navigation.\",\n CivicAuthErrorCode.INTERNAL_ERROR,\n ),\n );\n return;\n }\n this.logger.info(\"Navigating iframe to new URL\", { url });\n this.iframeElement.src = url;\n // After changing src, existing onload/onmessage handlers in IframeManager\n // and navigation monitoring in this class should manage visibility and state.\n }\n\n /**\n * Enable or disable iframe preloading\n */\n public setPreloadEnabled(enabled: boolean): void {\n this.isPreloadEnabled = enabled;\n this.logger.debug(\"Iframe preloading\", { enabled });\n }\n\n /**\n * Check if iframe preloading is enabled\n */\n public getPreloadEnabled(): boolean {\n return this.isPreloadEnabled;\n }\n\n /**\n * Check if an iframe is currently preloaded and ready for instant display\n *\n * This function helps optimize user experience by determining if we can show\n * a preloaded iframe immediately instead of loading a new one. The logic:\n *\n * 1. Returns false if no iframe manager exists (can't have preloaded content)\n * 2. Checks if any iframe is currently preloaded via the iframe manager\n * 3. If no specific URL is provided, returns whether any iframe is preloaded\n * 4. If a URL is provided, ensures both that an iframe is preloaded AND\n * that it contains the exact URL we need\n *\n * This prevents unnecessary iframe reloads when the user triggers auth flows\n * with the same URL that's already loaded and ready to display.\n *\n * @param url - Optional URL to match against the preloaded iframe's URL\n * @returns true if a suitable preloaded iframe exists, false otherwise\n */\n public hasPreloadedIframe(url?: string): boolean {\n if (!this.iframeManager) return false;\n\n const isPreloaded = this.iframeManager.isIframePreloaded();\n if (!url) return isPreloaded;\n\n return isPreloaded && this.iframeManager.getPreloadedUrl() === url;\n }\n\n /**\n * Force the iframe to hide, even if it is currently showing\n *\n * This is useful for cleanup or when you want to ensure the iframe is not visible\n * regardless of its current state.\n */\n public forceHideIframe(): void {\n if (this.iframeManager) {\n this.iframeManager.hide();\n this.logger.debug(\"Forced iframe to hide\");\n } else {\n this.logger.warn(\n \"Cannot force hide iframe, iframe manager not initialized\",\n );\n }\n }\n\n /**\n * Force the iframe to show the loading indicator\n */\n public forceShowLoader(): void {\n if (this.iframeManager) {\n this.iframeManager.forceShowLoader();\n this.logger.debug(\"Forced iframe loader to show\");\n } else {\n this.logger.warn(\n \"Cannot force show loader, iframe manager not initialized\",\n );\n }\n }\n}\n"]}
1
+ {"version":3,"file":"IframeAuthHandler.js","sourceRoot":"","sources":["../../../../src/vanillajs/auth/handlers/IframeAuthHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { AuthEvent } from \"../../types/index.js\";\nimport type { AuthResult } from \"../../types/index.js\";\nimport type { ProcessedCivicAuthConfig } from \"../types/AuthTypes.js\";\nimport { CivicAuthError, CivicAuthErrorCode } from \"../types/AuthTypes.js\";\nimport { SignalObserver } from \"../../iframe/SignalObserver.js\";\nimport { IframeManager } from \"../../iframe/IframeManager.js\";\nimport type { createLogger } from \"../../utils/logger.js\";\nimport { createLogger as createLoggerFn } from \"../../utils/logger.js\";\nimport { WAIT_FOR_LOGIN_APP_BROWSER_DETECTION_TIMEOUT } from \"@/constants.js\";\n\nexport interface IframeAuthHandlerConfig {\n config: ProcessedCivicAuthConfig;\n logger: ReturnType<typeof createLogger>;\n onAuthSuccess: (result: AuthResult) => void;\n onAuthError: (error: Error) => void;\n cleanup: () => void;\n messageHandler: (event: MessageEvent) => void;\n}\n\nexport class IframeAuthHandler {\n private config: ProcessedCivicAuthConfig;\n private logger = createLoggerFn(\"iframe-auth\");\n private onAuthSuccess: (result: AuthResult) => void;\n private onAuthError: (error: Error) => void;\n private cleanup: () => void;\n private messageHandler: (event: MessageEvent) => void;\n private iframeManager?: IframeManager;\n private iframeElement?: HTMLIFrameElement;\n private signalObserver?: SignalObserver;\n private earlyAuthSuccessHandler: (event: CustomEvent) => void;\n private isPreloadEnabled: boolean; // Initialized from config\n\n constructor(handlerConfig: IframeAuthHandlerConfig) {\n this.config = handlerConfig.config;\n this.logger = handlerConfig.logger;\n this.onAuthSuccess = handlerConfig.onAuthSuccess;\n this.onAuthError = handlerConfig.onAuthError;\n this.cleanup = handlerConfig.cleanup;\n this.messageHandler = handlerConfig.messageHandler;\n\n // Set preload enabled state from config\n this.isPreloadEnabled = this.config.preloadIframe;\n\n // Listen for early auth success signals from login-app\n this.earlyAuthSuccessHandler = (event: CustomEvent) => {\n this.logger.info(\"Received early auth success signal from login-app\", {\n detail: event.detail,\n });\n\n // Close the modal immediately but keep iframe for callback processing\n if (this.iframeManager) {\n this.logger.info(\"Closing modal early due to auth success signal\");\n this.iframeManager.hide();\n\n // Emit event to notify that modal is closing early\n this.config.events?.emit(AuthEvent.SIGN_IN_STARTED, {\n detail: \"Modal closed early due to auth success signal\",\n });\n }\n };\n\n window.addEventListener(\n \"civic-auth-success-early\",\n this.earlyAuthSuccessHandler as EventListener,\n );\n\n // Set up postMessage listener for cross-origin communication\n window.addEventListener(\"message\", this.messageHandler);\n }\n\n /**\n * Preloads the iframe with the authentication URL for instant display later\n * This creates the iframe in the background but keeps it completely hidden\n */\n public async preloadIframe(fullAuthUrl: string): Promise<void> {\n if (!this.isPreloadEnabled) {\n this.logger.debug(\"Iframe preloading is disabled, skipping preload\");\n return;\n }\n\n this.logger.debug(\"Preloading iframe for instant sign-in\", {\n url: fullAuthUrl,\n });\n\n // Determine the actual display mode for IframeManager first\n const iframeDisplayMode = this.determineIframeDisplayMode();\n\n let container = this.getContainerElement();\n\n // For modal mode, if no container is provided, create one dynamically\n if (iframeDisplayMode === \"modal\" && !container) {\n container = this.createModalContainer();\n }\n\n if (!container) {\n const error = new CivicAuthError(\n \"Target container element not found for preloading. \" +\n \"For embedded iframe mode, provide a targetContainerElement or ensure an element with id 'civic-login-container' exists.\",\n CivicAuthErrorCode.CONTAINER_NOT_FOUND,\n );\n this.logger.error(error.message);\n throw error;\n }\n\n this.logger.debug(\"Creating IframeManager for preloading\", {\n url: fullAuthUrl,\n containerId: container?.id,\n iframeId: this.config.iframeId,\n origin: window.location.origin,\n iframeDisplayMode,\n });\n\n // Create IframeManager with appropriate display mode\n this.iframeManager = new IframeManager({\n container: container,\n displayMode: iframeDisplayMode,\n iframeId: this.config.iframeId,\n onClose: () => {\n this.logger.debug(\"Authentication close requested during preload\");\n // For preload, we don't want to trigger auth error, just cleanup\n this.cleanupIframe();\n },\n });\n\n // Preload the iframe using IframeManager\n this.iframeElement = this.iframeManager.preloadIframe(fullAuthUrl);\n\n // Set up event handlers for the preloaded iframe\n this.setupIframeEventHandlers();\n this.setupIframeNavigationMonitoring();\n\n this.logger.debug(\"Iframe preloaded successfully\", { url: fullAuthUrl });\n }\n\n public async handleIframeAuth(\n fullAuthUrl: string,\n ): Promise<HTMLIFrameElement> {\n // Check if we have a preloaded iframe that we can show instantly\n // We use the preloaded iframe if available, even if URLs don't exactly match,\n // since PKCE challenges and other parameters may differ between preload and actual auth\n if (this.iframeManager?.isIframePreloaded() && this.iframeElement) {\n const preloadedUrl = this.iframeManager.getPreloadedUrl();\n this.logger.debug(\"Using preloaded iframe for instant sign-in\", {\n preloadedUrl,\n requestedUrl: fullAuthUrl,\n urlsMatch: preloadedUrl === fullAuthUrl,\n });\n\n // Don't change iframe.src for preloaded iframes - use them as-is to avoid reload\n // The preloaded authentication flow will work perfectly without URL changes\n this.logger.debug(\"Using preloaded iframe without reload\", {\n preloadedUrl,\n requestedUrl: fullAuthUrl,\n action: \"skipping_url_change_to_prevent_reload\",\n });\n\n // Update the onClose handler for active authentication\n // During preload, onClose only cleaned up, but during active auth it should emit error events\n this.iframeManager.updateOnCloseHandler(() => {\n this.logger.debug(\n \"Authentication close requested by user (backdrop click, close button, or Escape key)\",\n );\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Authentication cancelled by user\",\n });\n\n const error = new CivicAuthError(\n \"Authentication cancelled by user\",\n CivicAuthErrorCode.USER_CANCELLED,\n );\n\n this.onAuthError(error);\n this.cleanup();\n });\n\n // Show the preloaded iframe instantly\n this.iframeElement = this.iframeManager.createIframe(fullAuthUrl);\n\n this.config.events?.emit(AuthEvent.SIGN_IN_STARTED, {\n detail: \"Preloaded iframe displayed instantly\",\n });\n\n return this.iframeElement;\n }\n\n // Fallback to creating a new iframe if no preload is available\n this.logger.debug(\"No preloaded iframe available, creating new iframe\", {\n url: fullAuthUrl,\n });\n\n // Determine the actual display mode for IframeManager first\n const iframeDisplayMode = this.determineIframeDisplayMode();\n\n let container = this.getContainerElement();\n\n // For modal mode, if no container is provided, create one dynamically\n if (iframeDisplayMode === \"modal\" && !container) {\n container = this.createModalContainer();\n }\n\n if (!container) {\n const error = new CivicAuthError(\n \"Target container element not found. \" +\n \"For embedded iframe mode, provide a targetContainerElement or ensure an element with class id 'civic-login-container' exists.\",\n CivicAuthErrorCode.CONTAINER_NOT_FOUND,\n );\n this.logger.error(error.message);\n throw error;\n }\n\n this.logger.debug(\"Creating iframe with modal backdrop\", {\n url: fullAuthUrl,\n containerId: container?.id,\n iframeId: this.config.iframeId,\n origin: window.location.origin,\n iframeDisplayMode,\n containerCreated:\n iframeDisplayMode === \"modal\" && !this.config.targetContainerElement,\n });\n\n this.logger.debug(\n `🎯 CivicAuth: Creating IframeManager with display mode: ${iframeDisplayMode}`,\n );\n\n // Create IframeManager with appropriate display mode\n this.iframeManager = new IframeManager({\n container: container,\n displayMode: iframeDisplayMode,\n iframeId: this.config.iframeId,\n /**\n * Handles iframe closure events initiated by the user.\n * This includes backdrop clicks, close button clicks, or Escape key presses.\n * Emits an error event and cleans up the authentication process.\n */\n onClose: () => {\n this.logger.debug(\n \"Authentication close requested by user (backdrop click, close button, or Escape key)\",\n );\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Authentication cancelled by user\",\n });\n\n const error = new CivicAuthError(\n \"Authentication cancelled by user\",\n CivicAuthErrorCode.USER_CANCELLED,\n );\n\n this.onAuthError(error);\n this.cleanup();\n },\n });\n\n // Create the iframe using IframeManager\n this.iframeElement = this.iframeManager.createIframe(fullAuthUrl);\n\n this.config.events?.emit(AuthEvent.SIGN_IN_STARTED, {\n detail: \"Iframe created with modal backdrop\",\n });\n\n this.setupIframeEventHandlers();\n this.setupIframeNavigationMonitoring();\n\n return this.iframeElement;\n }\n\n public getIframeManager(): IframeManager | undefined {\n return this.iframeManager;\n }\n\n public getIframeElement(): HTMLIFrameElement | undefined {\n return this.iframeElement;\n }\n\n public cleanupIframe(): void {\n this.logger.debug(\"Cleaning up iframe manager\");\n\n // Check if we're in embedded mode - if so, preserve the iframe completely\n const isEmbeddedMode = this.iframeManager?.getDisplayMode() === \"embedded\";\n\n if (isEmbeddedMode) {\n // For embedded mode, do NOT cleanup anything - keep iframe visible in its current state\n this.logger.debug(\n \"Embedded mode detected - preserving iframe in its current state, no cleanup\",\n );\n // Only clean up event listeners but keep iframe and all DOM structure intact\n if (this.earlyAuthSuccessHandler) {\n window.removeEventListener(\n \"civic-auth-success-early\",\n this.earlyAuthSuccessHandler as EventListener,\n );\n }\n // Keep iframe element reference for embedded mode\n return;\n }\n\n // For modal mode, do full cleanup as before\n this.iframeManager?.cleanup();\n this.iframeManager = undefined;\n\n if (this.iframeElement) {\n this.iframeElement = undefined;\n }\n\n // Remove early auth success event listener\n if (this.earlyAuthSuccessHandler) {\n window.removeEventListener(\n \"civic-auth-success-early\",\n this.earlyAuthSuccessHandler as EventListener,\n );\n }\n\n // Clean up dynamically created modal containers\n this.cleanupDynamicModalContainer();\n }\n\n private cleanupDynamicModalContainer(): void {\n // Only clean up containers we created dynamically (not user-provided ones)\n if (!this.config.targetContainerElement) {\n const dynamicContainer = document.querySelector(\n `[data-civic-auth-modal=\"true\"]#${this.config.iframeId}-modal-container`,\n );\n\n if (dynamicContainer && dynamicContainer.parentNode) {\n this.logger.debug(\"Removing dynamic modal container\", {\n containerId: dynamicContainer.id,\n });\n dynamicContainer.parentNode.removeChild(dynamicContainer);\n }\n }\n }\n\n private createModalContainer(): HTMLElement {\n const container = document.createElement(\"div\");\n container.id = `${this.config.iframeId}-modal-container`;\n container.setAttribute(\"data-civic-auth-modal\", \"true\");\n\n // Append to body for modal overlay\n document.body.appendChild(container);\n\n this.logger.debug(\"Created dynamic modal container\", {\n containerId: container.id,\n });\n\n return container;\n }\n\n private getContainerElement(): HTMLElement | null {\n if (typeof this.config.targetContainerElement === \"string\") {\n const element = document.getElementById(\n this.config.targetContainerElement,\n );\n if (!element) {\n this.logger.warn(\n `Container element with ID \"${this.config.targetContainerElement}\" not found`,\n );\n }\n return element;\n }\n\n if (this.config.targetContainerElement) {\n return this.config.targetContainerElement;\n }\n\n // Fallback: Look for element with id \"civic-login-container\"\n const fallbackContainer = document.getElementById(\n \"civic-login-container\",\n ) as HTMLElement;\n if (fallbackContainer) {\n this.logger.debug(\n 'Using fallback container with id \"civic-login-container\"',\n );\n return fallbackContainer;\n }\n\n return null;\n }\n\n private determineIframeDisplayMode(): \"modal\" | \"embedded\" {\n // Priority 1: Explicit iframeDisplayMode setting from config\n // This is the most specific instruction for how the iframe itself should be styled.\n if (this.config.iframeDisplayMode) {\n this.logger.debug(\n `Using configured iframeDisplayMode: ${this.config.iframeDisplayMode}`,\n );\n return this.config.iframeDisplayMode;\n }\n\n // Priority 2: If iframeDisplayMode is NOT set, and the overall displayMode is \"iframe\",\n // default the iframe's own rendering style to \"modal\" (user-friendly default).\n // To get an embedded iframe, iframeDisplayMode: \"embedded\" should be set explicitly.\n if (this.config.displayMode === \"iframe\") {\n this.logger.debug(\n \"Overall displayMode is 'iframe' and iframeDisplayMode is not set, defaulting iframe style to 'modal'.\",\n );\n return \"modal\";\n }\n\n // Fallback for unexpected scenarios or if IframeAuthHandler is invoked with other displayModes.\n this.logger.warn(\n `determineIframeDisplayMode called with overall displayMode: '${this.config.displayMode}' ` +\n `and no explicit iframeDisplayMode. Defaulting iframe style to 'modal'.`,\n );\n return \"modal\";\n }\n\n private setupIframeEventHandlers(): void {\n if (!this.iframeElement) return;\n\n this.iframeElement.onload = () => {\n this.logger.info(\"Iframe loaded\", {\n iframeSrc: this.iframeElement?.src,\n currentOrigin: window.location.origin,\n expectedAuthServerOrigin: new URL(this.config.oauthServerBaseUrl)\n .origin,\n });\n\n if (!this.iframeElement?.contentWindow) {\n const errorMsg = \"Iframe content window not available after load.\";\n this.logger.error(errorMsg, {\n iframeSrc: this.iframeElement?.src,\n });\n\n const error = new Error(errorMsg);\n this.onAuthError(error);\n this.cleanup();\n return;\n }\n this.logger.info(\n \"Added cross-origin message event listener for auth server communication\",\n {\n parentOrigin: window.location.origin,\n authServerOrigin: new URL(this.config.oauthServerBaseUrl).origin,\n },\n );\n\n // Hide iframe content if it's not the login app\n this.checkAndHideNonLoginContent();\n\n // Try to detect redirect to our domain\n this.checkIframeRedirect();\n };\n\n this.iframeElement.onerror = (event) => {\n this.logger.error(\"Iframe load error\", {\n event,\n iframeSrc: this.iframeElement?.src,\n currentOrigin: window.location.origin,\n });\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Iframe load error\",\n error: event,\n });\n\n const error = new Error(\"Iframe failed to load.\");\n this.onAuthError(error);\n this.cleanup();\n };\n }\n\n private checkAndHideNonLoginContent(): void {\n try {\n const currentUrl = this.iframeElement?.contentWindow?.location.href;\n if (currentUrl) {\n const currentOrigin = new URL(currentUrl).origin;\n const expectedAuthServerOrigin = this.config.oauthServerBaseUrl\n ? new URL(this.config.oauthServerBaseUrl).origin\n : null;\n const isOnAuthServer = expectedAuthServerOrigin\n ? currentOrigin === expectedAuthServerOrigin\n : false;\n const isCallbackUrl = this.config.redirectUrl\n ? currentUrl.startsWith(this.config.redirectUrl)\n : false;\n\n if (isOnAuthServer && !isCallbackUrl) {\n this.logger.info(\n \"👀 Showing iframe content - confirmed login app on auth server origin\",\n {\n currentUrl,\n isOnAuthServer,\n isCallbackUrl,\n currentOrigin,\n expectedAuthServerOrigin,\n },\n );\n this.iframeManager?.forceHideLoader();\n } else {\n this.logger.info(\n \"🙈 Hiding iframe completely - not login app or on callback URL\",\n {\n currentUrl,\n isOnAuthServer,\n isCallbackUrl,\n currentOrigin,\n expectedAuthServerOrigin,\n reason: !isOnAuthServer\n ? expectedAuthServerOrigin\n ? \"not on auth server (origin mismatch)\"\n : \"auth server origin unknown\"\n : \"on callback URL (or origin mismatch for login page)\",\n },\n );\n\n if (isCallbackUrl) {\n this.iframeManager?.hide();\n } else {\n this.iframeManager?.forceShowLoader();\n }\n }\n }\n } catch (error) {\n this.logger.debug(\n \"Cannot access iframe URL (likely cross-origin) - assuming login app, showing content.\",\n { error: error instanceof Error ? error.message : String(error) },\n );\n setTimeout(() => {\n // Force hide loader after a short delay to ensure any initial loading is complete\n // to give the login-app time to send any post message signals\n this.iframeManager?.forceHideLoader();\n }, WAIT_FOR_LOGIN_APP_BROWSER_DETECTION_TIMEOUT);\n }\n }\n\n private checkIframeRedirect(): void {\n try {\n const currentIframeHref =\n this.iframeElement?.contentWindow?.location.href;\n\n if (currentIframeHref) {\n this.logger.debug(\"Iframe current href accessible\", {\n href: currentIframeHref,\n redirectUrl: this.config.redirectUrl,\n startsWithRedirect: currentIframeHref.startsWith(\n this.config.redirectUrl,\n ),\n });\n\n if (currentIframeHref.startsWith(this.config.redirectUrl)) {\n this.logger.info(\n \"Iframe has navigated to redirectUrl (same-origin). Setting up DOM observer.\",\n );\n\n // Hide content since we're on callback page now\n this.checkAndHideNonLoginContent();\n\n // Set up signal observer for same-origin callback page\n if (\n this.iframeElement?.contentDocument &&\n this.iframeElement.contentDocument.body\n ) {\n this.setupSignalObserver(this.iframeElement.contentDocument);\n } else {\n this.logger.warn(\n \"Iframe content document or body not available for signal observer\",\n );\n }\n }\n }\n } catch (error) {\n this.logger.debug(\n \"Error checking iframe href (expected for cross-origin)\",\n {\n error: error instanceof Error ? error.message : String(error),\n iframeSrc: this.iframeElement?.src,\n },\n );\n // This is expected when the iframe is on the auth server domain\n this.logger.info(\n \"Iframe is on auth server domain - using postMessage for communication\",\n {\n parentOrigin: window.location.origin,\n authServerOrigin: new URL(this.config.oauthServerBaseUrl).origin,\n },\n );\n }\n }\n\n private setupSignalObserver(iframeDoc: Document): void {\n this.logger.info(\"📝 Setting up SignalObserver\", {\n documentURL: iframeDoc.URL,\n documentTitle: iframeDoc.title,\n bodyExists: !!iframeDoc.body,\n textSignals: this.config.textSignals,\n hasEvents: !!this.config.events,\n });\n\n const signalObserver = new SignalObserver(\n {\n textSignals: this.config.textSignals,\n events: this.config.events,\n logger: this.logger,\n },\n this.onAuthSuccess,\n (error?: Error) =>\n this.onAuthError(error || new Error(\"Signal observer error\")),\n () => this.cleanup(),\n );\n\n this.signalObserver = signalObserver; // Store reference\n\n try {\n signalObserver.setup(iframeDoc);\n this.logger.info(\"✅ SignalObserver setup completed successfully\");\n } catch (error) {\n this.logger.error(\"❌ SignalObserver setup failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n private setupIframeNavigationMonitoring(): void {\n // Monitor iframe navigation to detect when it redirects to our callback URL\n let monitoringInterval: number | undefined = undefined;\n let lastKnownUrl = \"\";\n\n const checkIframeNavigation = () => {\n if (!this.iframeElement?.contentWindow) {\n if (monitoringInterval) {\n clearInterval(monitoringInterval);\n }\n return;\n }\n\n try {\n const currentUrl = this.iframeElement.contentWindow.location.href;\n\n if (currentUrl !== lastKnownUrl) {\n lastKnownUrl = currentUrl;\n this.logger.info(\"🔍 Iframe navigation detected\", {\n newUrl: currentUrl,\n redirectUrl: this.config.redirectUrl,\n isCallbackUrl: currentUrl.startsWith(this.config.redirectUrl),\n });\n\n // Check if iframe has navigated to our callback URL\n if (currentUrl.startsWith(this.config.redirectUrl)) {\n // Hide immediately on callback URL detection\n this.iframeManager?.hide();\n this.logger.info(\n \"🎯 Iframe navigated to callback URL - setting up signal observer\",\n {\n callbackUrl: currentUrl,\n hasContentDocument: !!this.iframeElement.contentDocument,\n hasBody: !!this.iframeElement.contentDocument?.body,\n },\n );\n\n if (monitoringInterval) {\n clearInterval(monitoringInterval);\n }\n\n // Set up signal observer for same-origin callback page\n if (\n this.iframeElement.contentDocument &&\n this.iframeElement.contentDocument.body\n ) {\n this.logger.info(\n \"✅ Setting up SignalObserver for callback page\",\n {\n documentReady: !!this.iframeElement.contentDocument,\n bodyReady: !!this.iframeElement.contentDocument.body,\n documentURL: this.iframeElement.contentDocument.URL,\n },\n );\n this.setupSignalObserver(this.iframeElement.contentDocument);\n } else {\n this.logger.warn(\n \"❌ Cannot set up SignalObserver - iframe document not accessible\",\n {\n hasContentDocument: !!this.iframeElement.contentDocument,\n hasBody: !!this.iframeElement.contentDocument?.body,\n iframeReady: !!this.iframeElement,\n },\n );\n }\n\n // Also check for URL parameters (code, error) in case of direct callback\n this.processCallbackUrl(currentUrl);\n } else {\n // Hide content if not on login app\n this.checkAndHideNonLoginContent();\n }\n }\n } catch {\n // Expected when iframe is on different origin\n // Only log if we haven't seen this before\n if (lastKnownUrl !== \"cross-origin\") {\n lastKnownUrl = \"cross-origin\";\n this.logger.debug(\n \"Iframe on cross-origin domain (expected during auth flow)\",\n );\n }\n }\n };\n\n // Check immediately and then every 100ms for faster detection\n checkIframeNavigation();\n monitoringInterval = window.setInterval(checkIframeNavigation, 100);\n\n // Store cleanup function to clear monitoring\n const originalCleanup = this.cleanup;\n this.cleanup = () => {\n if (monitoringInterval) {\n clearInterval(monitoringInterval);\n }\n originalCleanup();\n };\n }\n\n private processCallbackUrl(currentUrl: string): void {\n const urlParams = new URLSearchParams(new URL(currentUrl).search);\n const code = urlParams.get(\"code\");\n const error = urlParams.get(\"error\");\n\n if (code) {\n this.logger.info(\"Authorization code detected in iframe URL\", {\n code: code.substring(0, 10) + \"...\",\n hasState: !!urlParams.get(\"state\"),\n });\n }\n\n if (error) {\n this.logger.error(\"OAuth error detected in iframe URL\", {\n error,\n errorDescription: urlParams.get(\"error_description\"),\n });\n\n const authError = new CivicAuthError(\n `OAuth error: ${error}`,\n CivicAuthErrorCode.INVALID_MESSAGE,\n );\n\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: authError.message,\n error: urlParams.get(\"error_description\") || error,\n });\n\n this.onAuthError(authError);\n }\n }\n\n public navigateIframe(url: string): void {\n if (!this.iframeElement) {\n this.logger.error(\n \"Cannot navigate iframe, iframeElement is not available.\",\n );\n this.onAuthError(\n new CivicAuthError(\n \"Iframe element not found for navigation.\",\n CivicAuthErrorCode.IFRAME_NOT_FOUND,\n ),\n );\n return;\n }\n if (!this.iframeManager) {\n this.logger.error(\n \"Cannot navigate iframe, iframeManager is not available.\",\n );\n this.onAuthError(\n new CivicAuthError(\n \"Iframe manager not found for navigation.\",\n CivicAuthErrorCode.INTERNAL_ERROR,\n ),\n );\n return;\n }\n this.logger.info(\"Navigating iframe to new URL\", { url });\n this.iframeElement.src = url;\n // After changing src, existing onload/onmessage handlers in IframeManager\n // and navigation monitoring in this class should manage visibility and state.\n }\n\n /**\n * Enable or disable iframe preloading\n */\n public setPreloadEnabled(enabled: boolean): void {\n this.isPreloadEnabled = enabled;\n this.logger.debug(\"Iframe preloading\", { enabled });\n }\n\n /**\n * Check if iframe preloading is enabled\n */\n public getPreloadEnabled(): boolean {\n return this.isPreloadEnabled;\n }\n\n /**\n * Check if an iframe is currently preloaded and ready for instant display\n *\n * This function helps optimize user experience by determining if we can show\n * a preloaded iframe immediately instead of loading a new one. The logic:\n *\n * 1. Returns false if no iframe manager exists (can't have preloaded content)\n * 2. Checks if any iframe is currently preloaded via the iframe manager\n * 3. If no specific URL is provided, returns whether any iframe is preloaded\n * 4. If a URL is provided, ensures both that an iframe is preloaded AND\n * that it contains the exact URL we need\n *\n * This prevents unnecessary iframe reloads when the user triggers auth flows\n * with the same URL that's already loaded and ready to display.\n *\n * @param url - Optional URL to match against the preloaded iframe's URL\n * @returns true if a suitable preloaded iframe exists, false otherwise\n */\n public hasPreloadedIframe(url?: string): boolean {\n if (!this.iframeManager) return false;\n\n const isPreloaded = this.iframeManager.isIframePreloaded();\n if (!url) return isPreloaded;\n\n return isPreloaded && this.iframeManager.getPreloadedUrl() === url;\n }\n\n /**\n * Force the iframe to hide, even if it is currently showing\n *\n * This is useful for cleanup or when you want to ensure the iframe is not visible\n * regardless of its current state.\n */\n public forceHideIframe(): void {\n if (this.iframeManager) {\n this.iframeManager.hide();\n this.logger.debug(\"Forced iframe to hide\");\n } else {\n this.logger.warn(\n \"Cannot force hide iframe, iframe manager not initialized\",\n );\n }\n }\n\n /**\n * Force the iframe to show the loading indicator\n */\n public forceShowLoader(): void {\n if (this.iframeManager) {\n this.iframeManager.forceShowLoader();\n this.logger.debug(\"Forced iframe loader to show\");\n } else {\n this.logger.warn(\n \"Cannot force show loader, iframe manager not initialized\",\n );\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"MessageHandler.d.ts","sourceRoot":"","sources":["../../../../src/vanillajs/auth/handlers/MessageHandler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAIV,wBAAwB,EACzB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAI1D,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,wBAAwB,CAAC;IACjC,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IACxC,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,aAAa,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAC5C,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACpC,cAAc,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,0BAA0B,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,aAAa,CAAC,CAAoB;IAC1C,OAAO,CAAC,aAAa,CAA+B;IACpD,OAAO,CAAC,WAAW,CAAyB;IAC5C,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,0BAA0B,CAG9B;IACJ,OAAO,CAAC,OAAO,CAAa;IAG5B,OAAO,CAAC,oBAAoB,CAAC,CAAS;gBAE1B,aAAa,EAAE,oBAAoB;IAU/C;;;;;;;;OAQG;IACI,mBAAmB,CAAC,aAAa,EAAE,iBAAiB,GAAG,IAAI;IAIlE;;;;;;;OAOG;IACI,uBAAuB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI;IAQ5D;;OAEG;IACI,yBAAyB,IAAI,IAAI;IAOxC;;;;;;;OAOG;IACI,aAAa,UAAW,YAAY,KAAG,IAAI,CAYhD;IAEF;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IAa1B;;;;;;;;;OASG;IACH,OAAO,CAAC,oBAAoB;IA6D5B;;;;;;;OAOG;IACH,OAAO,CAAC,kBAAkB;IAoC1B;;;;;;;;OAQG;IACH,OAAO,CAAC,sBAAsB;IAS9B;;;;;;;;OAQG;IACH,OAAO,CAAC,0BAA0B;IA6DlC;;;;;;;OAOG;IAEH,OAAO,CAAC,sBAAsB;IAc9B;;;;;;;OAOG;IACH,OAAO,CAAC,wBAAwB;IAoBhC;;;;;OAKG;IACH,OAAO,CAAC,8BAA8B;IAkBtC;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IA2B1B;;;;;;;OAOG;IACH,OAAO,CAAC,iCAAiC;IAqBzC;;;;;;;;OAQG;IACH,OAAO,CAAC,sBAAsB;IAY9B;;;;;;;OAOG;IACH,OAAO,CAAC,0BAA0B;IAYlC;;;;;;;OAOG;IACH,OAAO,CAAC,yBAAyB;IAmCjC;;;;;;;OAOG;IACH,OAAO,CAAC,iBAAiB;IASzB;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;CAcxB"}
1
+ {"version":3,"file":"MessageHandler.d.ts","sourceRoot":"","sources":["../../../../src/vanillajs/auth/handlers/MessageHandler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAIV,wBAAwB,EACzB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAI1D,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,wBAAwB,CAAC;IACjC,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IACxC,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,aAAa,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAC5C,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACpC,cAAc,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,0BAA0B,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,aAAa,CAAC,CAAoB;IAC1C,OAAO,CAAC,aAAa,CAA+B;IACpD,OAAO,CAAC,WAAW,CAAyB;IAC5C,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,0BAA0B,CAG9B;IACJ,OAAO,CAAC,OAAO,CAAa;IAG5B,OAAO,CAAC,oBAAoB,CAAC,CAAS;gBAE1B,aAAa,EAAE,oBAAoB;IAU/C;;;;;;;;OAQG;IACI,mBAAmB,CAAC,aAAa,EAAE,iBAAiB,GAAG,IAAI;IAIlE;;;;;;;OAOG;IACI,uBAAuB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI;IAQ5D;;OAEG;IACI,yBAAyB,IAAI,IAAI;IAOxC;;;;;;;OAOG;IACI,aAAa,UAAW,YAAY,KAAG,IAAI,CAYhD;IAEF;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IAa1B;;;;;;;;;OASG;IACH,OAAO,CAAC,oBAAoB;IA6D5B;;;;;;;OAOG;IACH,OAAO,CAAC,kBAAkB;IAoC1B;;;;;;;;OAQG;IACH,OAAO,CAAC,sBAAsB;IAS9B;;;;;;;;OAQG;IACH,OAAO,CAAC,0BAA0B;IA6DlC;;;;;;;OAOG;IAEH,OAAO,CAAC,sBAAsB;IAc9B;;;;;;;OAOG;IACH,OAAO,CAAC,wBAAwB;IAoBhC;;;;;OAKG;IACH,OAAO,CAAC,8BAA8B;IAkBtC;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IA8B1B;;;;;;;OAOG;IACH,OAAO,CAAC,iCAAiC;IAqBzC;;;;;;;;OAQG;IACH,OAAO,CAAC,sBAAsB;IAY9B;;;;;;;OAOG;IACH,OAAO,CAAC,0BAA0B;IAYlC;;;;;;;OAOG;IACH,OAAO,CAAC,yBAAyB;IAmCjC;;;;;;;OAOG;IACH,OAAO,CAAC,iBAAiB;IASzB;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;CAcxB"}
@@ -352,8 +352,11 @@ export class MessageHandler {
352
352
  failedUrl,
353
353
  displayMode: this.config.displayMode,
354
354
  });
355
- this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {
355
+ this.config.events?.emit(AuthEvent.URL_CHANGE, {
356
356
  detail: "Popup blocked by browser - switching to redirect mode",
357
+ url: failedUrl,
358
+ source: "login_app",
359
+ failedUrl,
357
360
  error: {
358
361
  type: "popup_blocked",
359
362
  failedUrl,
@@ -1 +1 @@
1
- {"version":3,"file":"MessageHandler.js","sourceRoot":"","sources":["../../../../src/vanillajs/auth/handlers/MessageHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { AuthEvent } from \"../../types/index.js\";\nimport type { AuthResult } from \"../../types/index.js\";\nimport type {\n IframeMessage,\n AuthMessage,\n LoginAppMessage,\n ProcessedCivicAuthConfig,\n} from \"../types/AuthTypes.js\";\nimport { CivicAuthError, CivicAuthErrorCode } from \"../types/AuthTypes.js\";\nimport type { createLogger } from \"../../utils/logger.js\";\nimport { createLogger as createLoggerFn } from \"../../utils/logger.js\";\nimport { IframeManager } from \"@/vanillajs/iframe/IframeManager.js\";\n\nexport interface MessageHandlerConfig {\n config: ProcessedCivicAuthConfig;\n logger: ReturnType<typeof createLogger>;\n iframeElement?: HTMLIFrameElement;\n onAuthSuccess: (result: AuthResult) => void;\n onAuthError: (error: Error) => void;\n onPopupFailure: (failedUrl?: string) => void;\n onBrowserCorsFailsSilently: (failedUrl?: string) => Promise<void>;\n cleanup: () => void;\n}\n\n/**\n * MessageHandler - Handles postMessage communication and authentication flow logic\n * Processes messages from iframe, validates origins, and manages auth state transitions\n */\nexport class MessageHandler {\n private config: ProcessedCivicAuthConfig;\n private logger = createLoggerFn(\"message-handler\");\n private iframeElement?: HTMLIFrameElement;\n private onAuthSuccess: (result: AuthResult) => void;\n private onAuthError: (error: Error) => void;\n private onPopupFailure: (failedUrl?: string) => void;\n private onBrowserCorsFailsSilently: (failedUrl?: string) => Promise<void> =\n () => {\n return Promise.resolve(); // No-op by default, can be overridden\n };\n private cleanup: () => void;\n\n // Backend integration - custom expected origin\n private customExpectedOrigin?: string;\n\n constructor(handlerConfig: MessageHandlerConfig) {\n this.config = handlerConfig.config;\n this.iframeElement = handlerConfig.iframeElement;\n this.onAuthSuccess = handlerConfig.onAuthSuccess;\n this.onAuthError = handlerConfig.onAuthError;\n this.onPopupFailure = handlerConfig.onPopupFailure;\n this.onBrowserCorsFailsSilently = handlerConfig.onBrowserCorsFailsSilently;\n this.cleanup = handlerConfig.cleanup;\n }\n\n /**\n * Updates the iframe element reference used for message validation.\n *\n * This method allows updating the iframe element after the MessageHandler\n * has been instantiated, which is useful when the iframe is created\n * dynamically after the handler setup.\n *\n * @param iframeElement - The new iframe element to associate with this handler\n */\n public updateIframeElement(iframeElement: HTMLIFrameElement): void {\n this.iframeElement = iframeElement;\n }\n\n /**\n * Sets a custom expected origin for backend integration.\n *\n * This allows the MessageHandler to accept messages from a custom backend\n * origin instead of the default OAuth server origin.\n *\n * @param customLoginUrl - The custom login URL to derive the origin from\n */\n public setCustomExpectedOrigin(customLoginUrl: string): void {\n this.customExpectedOrigin = new URL(customLoginUrl).origin;\n this.logger.info(\"🔗 Custom expected origin set for backend integration\", {\n customExpectedOrigin: this.customExpectedOrigin,\n customLoginUrl,\n });\n }\n\n /**\n * Clears the custom expected origin and returns to OAuth server origin.\n */\n public clearCustomExpectedOrigin(): void {\n this.customExpectedOrigin = undefined;\n this.logger.info(\n \"🔗 Custom expected origin cleared, returning to OAuth server origin\",\n );\n }\n\n /**\n * Main message handler for processing postMessage events.\n *\n * Validates message origin and source, then routes valid messages to\n * appropriate handlers. This is the entry point for all iframe communication.\n *\n * @param event - The MessageEvent received from the iframe or other sources\n */\n public handleMessage = (event: MessageEvent): void => {\n // Use custom origin if set (for backend integration), otherwise use OAuth server origin\n const expectedOrigin =\n this.customExpectedOrigin ||\n new URL(this.config.oauthServerBaseUrl).origin;\n this.logIncomingMessage(event, expectedOrigin);\n\n if (!this.isValidMessageSource(event, expectedOrigin)) {\n return;\n }\n\n this.handleValidMessage(event);\n };\n\n /**\n * Logs incoming message details for debugging purposes.\n *\n * Provides comprehensive logging of message properties including origin,\n * source validation, and iframe state for troubleshooting communication issues.\n *\n * @param event - The MessageEvent to log\n * @param expectedOrigin - The expected origin for comparison\n */\n private logIncomingMessage(\n event: MessageEvent,\n expectedOrigin: string,\n ): void {\n this.logger.debug(\"Global window received message:\", {\n data: event.data,\n origin: event.origin,\n sourceProvided: !!event.source,\n iframeContentWindow: this.iframeElement?.contentWindow,\n expectedIframeOrigin: expectedOrigin,\n });\n }\n\n /**\n * Validates that a message comes from the expected origin and source.\n *\n * Performs security checks to ensure messages are only processed from\n * the configured OAuth server origin and the designated iframe element.\n *\n * @param event - The MessageEvent to validate\n * @param expectedOrigin - The expected origin URL for the message\n * @returns True if the message source and origin are valid, false otherwise\n */\n private isValidMessageSource(\n event: MessageEvent,\n expectedOrigin: string,\n ): boolean {\n // Check if message is from the iframe source\n const isValidSource = event.source === this.iframeElement?.contentWindow;\n\n // Build list of allowed origins\n const allowedOrigins = [expectedOrigin];\n\n // Add the actual iframe origin (to handle redirects)\n if (this.iframeElement?.src) {\n try {\n const actualIframeOrigin = new URL(this.iframeElement.src).origin;\n allowedOrigins.push(actualIframeOrigin);\n } catch {\n // ignore URL parsing errors\n }\n }\n\n if (this.config.oauthServerBaseUrl) {\n allowedOrigins.push(new URL(this.config.oauthServerBaseUrl).origin);\n }\n\n // Add the client app's own origin (same-origin) for messages sent after token exchange\n // This is needed when the iframe navigates to the client app's callback URL\n const clientOrigin = window.location.origin;\n if (!allowedOrigins.includes(clientOrigin)) {\n allowedOrigins.push(clientOrigin);\n }\n\n // Add common development login app origins for localhost\n const expectedUrl = new URL(expectedOrigin);\n if (expectedUrl.hostname === \"localhost\") {\n // For localhost, also allow common development ports\n allowedOrigins.push(\"http://localhost:3004\"); // default login-app port\n allowedOrigins.push(\"http://localhost:3001\"); // auth server port\n }\n\n const isValidOrigin = allowedOrigins.includes(event.origin);\n\n if (!isValidOrigin) {\n this.logger.warn(\"Ignored message from unexpected origin.\", {\n receivedOrigin: event.origin,\n expectedOrigin,\n allowedOrigins,\n iframeSrc: this.iframeElement?.src,\n });\n }\n\n if (!isValidSource) {\n this.logger.warn(\"Ignored message from unexpected source.\", {\n isSourceProvided: !!event.source,\n isIframeContentWindowAvailable: !!this.iframeElement?.contentWindow,\n iframeSrc: this.iframeElement?.src,\n });\n }\n\n return isValidOrigin && isValidSource;\n }\n\n /**\n * Processes messages that have passed origin and source validation.\n *\n * Routes validated messages to specific handlers based on message type,\n * including civicloginApp messages, iframe resizer messages, and standard auth messages.\n *\n * @param event - The validated MessageEvent to process\n */\n private handleValidMessage(event: MessageEvent): void {\n this.logger.info(\n \"Message from configured iframe source and origin received\",\n {\n data: event.data,\n iframeSrc: this.iframeElement?.src,\n },\n );\n\n const message = event.data as IframeMessage;\n\n this.logger.debug(\"Processing iframe message\", {\n messageType: typeof message,\n hasType: message && typeof message === \"object\" && \"type\" in message,\n hasSource: message && typeof message === \"object\" && \"source\" in message,\n messageKeys:\n message && typeof message === \"object\" ? Object.keys(message) : [],\n rawData: message,\n });\n\n // Handle civicloginApp messages\n if (this.isCivicLoginAppMessage(message)) {\n this.handleCivicLoginAppMessage(message);\n return;\n }\n\n // Handle iframe resizer messages\n if (this.isIframeResizerMessage(message)) {\n this.handleIframeResizerMessage(message);\n return;\n }\n\n // Handle standard auth messages\n this.handleStandardAuthMessage(message);\n }\n\n /**\n * Type guard to identify civicloginApp messages.\n *\n * Checks if a message object has the structure and source property\n * that identifies it as coming from the civicloginApp.\n *\n * @param message - The message object to check\n * @returns True if the message is a LoginAppMessage, false otherwise\n */\n private isCivicLoginAppMessage(message: unknown): message is LoginAppMessage {\n return (\n message !== null &&\n typeof message === \"object\" &&\n \"source\" in message &&\n (message as Record<string, unknown>).source === \"civicloginApp\"\n );\n }\n\n /**\n * Handles messages originating from the civicloginApp.\n *\n * Processes various civicloginApp message types including authentication errors,\n * popup failures, design updates, and other app-specific communications.\n * Validates client ID matches before processing.\n *\n * @param message - The validated civicloginApp message to process\n */\n private handleCivicLoginAppMessage(message: LoginAppMessage): void {\n this.logger.info(\"Received civicloginApp message\", {\n type: message.type,\n clientId: message.clientId,\n data: message.data,\n });\n\n // Validate clientId matches our config\n if (\n message.clientId !== this.config.clientId &&\n this.config.loginUrl === undefined\n ) {\n this.logger.warn(\"civicloginApp message clientId mismatch\", {\n received: message.clientId,\n expected: this.config.clientId,\n });\n return;\n }\n\n switch (message.type) {\n case \"auth_error\":\n case \"auth_error_try_again\":\n this.handleCivicLoginAppError(message);\n break;\n case \"generatePopupFailed\":\n this.handlePopupFailure(message);\n break;\n case \"browserCorsFailsSilently\":\n this.handleBrowserCorsFailsSilently(message);\n break;\n case \"design\":\n this.logger.debug(\"civicloginApp design message\", {\n data: message.data,\n });\n break;\n case \"auth_success_early\":\n this.logger.info(\"civicloginApp auth success early message\", {\n data: message.data,\n });\n this.handleAuthSuccessEarly(message);\n break;\n case \"auth_success\":\n this.logger.info(\"civicloginApp auth success message\", {\n data: message.data,\n });\n\n // Dispatch early auth success event for immediate modal closing\n\n // Still handle auth success normally (for callback processing)\n this.handleAuthSuccess({\n type: \"auth_success\",\n detail: \"Authentication successful\",\n data: message.data,\n });\n break;\n default:\n this.handleUnknownCivicLoginAppMessage(message);\n break;\n }\n }\n\n /**\n * Handles auth success early messages from civicloginApp.\n *\n * Processes auth_success_early messages, emits success events,\n * and triggers the success callback with authentication results.\n *\n * @param message - The civicloginApp auth success early message to process\n */\n\n private handleAuthSuccessEarly(message: LoginAppMessage): void {\n this.logger.info(\"civicloginApp auth success early message\", {\n data: message.data,\n });\n\n const earlySuccessEvent = new CustomEvent(\"civic-auth-success-early\", {\n detail: {\n clientId: message.clientId,\n data: message.data,\n },\n });\n window.dispatchEvent(earlySuccessEvent);\n }\n\n /**\n * Handles authentication error messages from civicloginApp.\n *\n * Processes auth_error and auth_error_try_again messages, creates\n * appropriate error objects, emits error events, and triggers cleanup.\n *\n * @param message - The civicloginApp error message to process\n */\n private handleCivicLoginAppError(message: LoginAppMessage): void {\n this.logger.error(\"civicloginApp authentication error\", {\n type: message.type,\n data: message.data,\n });\n\n const error = new CivicAuthError(\n `Login app error: ${message.type}`,\n CivicAuthErrorCode.INVALID_MESSAGE,\n );\n\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: error.message,\n error: message.data,\n });\n\n this.onAuthError(error);\n this.cleanup();\n }\n\n /**\n * Handle the case where we know in advance that the browser will not prompt the user to open\n * a popup and will fail silently instead. We want to handle this case gracefully by switching to redirect\n * mode if the iframe is in modal display mode. This will be done when the auth flow actually starts\n * @param message\n */\n private handleBrowserCorsFailsSilently(message: LoginAppMessage): void {\n const failedUrl = (message.data as Record<string, unknown> | undefined)\n ?.url as string | undefined;\n this.logger.warn(\"civicloginApp browser CORS fail silently\", {\n failedUrl,\n config: this.config,\n autoRedirect: this.config.autoRedirect,\n });\n if (\n this.config.displayMode === \"iframe\" &&\n this.config.iframeDisplayMode === \"modal\" &&\n this.config.autoRedirect !== false && // Add this check\n failedUrl\n ) {\n IframeManager.handleBrowserCorsFailsSilently(failedUrl);\n this.onBrowserCorsFailsSilently(failedUrl);\n }\n }\n /**\n * Handles popup generation failure messages from civicloginApp.\n *\n * Processes generatePopupFailed messages, extracts the failed URL,\n * emits appropriate events, and triggers the popup failure callback\n * to enable fallback authentication methods.\n *\n * @param message - The civicloginApp popup failure message to process\n */\n private handlePopupFailure(message: LoginAppMessage): void {\n this.logger.warn(\"civicloginApp popup generation failed\", {\n data: message.data,\n });\n\n const failedUrl = (message.data as Record<string, unknown> | undefined)\n ?.url as string | undefined;\n if (failedUrl) {\n this.logger.info(\"Popup failed for URL, considering fallback options\", {\n failedUrl,\n displayMode: this.config.displayMode,\n });\n\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Popup blocked by browser - switching to redirect mode\",\n error: {\n type: \"popup_blocked\",\n failedUrl,\n suggestion:\n \"The browser blocked a popup window. Redirecting to complete authentication in a new page.\",\n },\n });\n }\n\n this.onPopupFailure(failedUrl);\n }\n\n /**\n * Handles unknown or unrecognized civicloginApp message types.\n *\n * Provides fallback handling for unexpected message types, with special\n * logic to detect potential success messages that don't match standard types.\n *\n * @param message - The unrecognized civicloginApp message to process\n */\n private handleUnknownCivicLoginAppMessage(message: LoginAppMessage): void {\n this.logger.debug(\"Unhandled civicloginApp message type\", {\n type: message.type,\n data: message.data,\n });\n\n // Check if this might be a success message with a different type\n if (message.type && message.type.toLowerCase().includes(\"success\")) {\n this.logger.info(\"Potential success message from civicloginApp\", {\n type: message.type,\n data: message.data,\n });\n\n this.handleAuthSuccess({\n type: \"auth_success\",\n detail: `civicloginApp success: ${message.type}`,\n data: message.data,\n });\n }\n }\n\n /**\n * Type guard to identify iframe resizer messages.\n *\n * Checks if a message is related to iframe resizing functionality,\n * including both civic-specific resize messages and iFrameResizerChild messages.\n *\n * @param message - The message object to check\n * @returns True if the message is an iframe resizer message, false otherwise\n */\n private isIframeResizerMessage(message: unknown): boolean {\n return (\n (message !== null &&\n typeof message === \"object\" &&\n \"type\" in message &&\n ((message as Record<string, unknown>).type === \"civic-iframe-resize\" ||\n (message as Record<string, unknown>).type ===\n \"civic-iframe-ready\")) ||\n (typeof message === \"string\" && message.includes(\"iFrameResizerChild\"))\n );\n }\n\n /**\n * Handles iframe resizer messages for dynamic iframe sizing.\n *\n * Processes messages related to iframe resizing, including height adjustments\n * and ready state notifications from the iframe resizer library.\n *\n * @param message - The iframe resizer message to process\n */\n private handleIframeResizerMessage(message: unknown): void {\n if (typeof message === \"string\") {\n this.logger.debug(\"Received iframe resizer child message\", { message });\n } else if (message && typeof message === \"object\" && message !== null) {\n const messageObj = message as Record<string, unknown>;\n this.logger.debug(\"Received iframe resizer message\", {\n type: messageObj.type,\n height: messageObj.height,\n });\n }\n }\n\n /**\n * Handles standard authentication messages.\n *\n * Processes auth_success and auth_error messages that follow the standard\n * authentication message format, routing them to appropriate success or error handlers.\n *\n * @param message - The standard auth message to process\n */\n private handleStandardAuthMessage(message: unknown): void {\n const messageObj =\n message && typeof message === \"object\" && message !== null\n ? (message as Record<string, unknown>)\n : null;\n const messageType = messageObj?.type;\n\n switch (messageType) {\n case \"auth_success\":\n this.handleAuthSuccess(message as AuthMessage);\n break;\n case \"auth_error\":\n this.handleAuthError(message as AuthMessage);\n break;\n default:\n // Check if this is a calculateSubFramePositioning message (expected and harmless)\n if (messageObj?.command === \"calculateSubFramePositioning\") {\n this.logger.debug(\"Received iframe positioning message (expected)\", {\n command: messageObj.command,\n hasSubFrameData: !!messageObj.subFrameData,\n });\n } else {\n this.logger.debug(\n \"Message from iframe did not match expected types (auth_success, auth_error, civicloginApp, iframe-resizer)\",\n {\n data: message,\n messageType: typeof message,\n hasType: messageObj?.type ?? \"none\",\n messageKeys: messageObj ? Object.keys(messageObj) : [],\n },\n );\n }\n }\n }\n\n /**\n * Handles successful authentication completion.\n *\n * Processes authentication success messages, emits success events,\n * triggers the success callback with authentication results, and performs cleanup.\n *\n * @param data - The authentication success message containing result data\n */\n private handleAuthSuccess(data: AuthMessage): void {\n this.config.events?.emit(AuthEvent.SIGN_IN_COMPLETE, {\n detail: \"Success signal received via postMessage\",\n data,\n });\n this.onAuthSuccess((data?.data as AuthResult) || {});\n this.cleanup();\n }\n\n /**\n * Handles authentication errors.\n *\n * Processes authentication error messages, creates appropriate error objects,\n * emits error events, triggers the error callback, and performs cleanup.\n *\n * @param data - The authentication error message containing error details\n */\n private handleAuthError(data: AuthMessage): void {\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Error signal received via postMessage\",\n error: data,\n });\n\n const error = new CivicAuthError(\n data?.detail || \"Error signal received via postMessage\",\n CivicAuthErrorCode.INVALID_MESSAGE,\n );\n\n this.onAuthError(error);\n this.cleanup();\n }\n}\n"]}
1
+ {"version":3,"file":"MessageHandler.js","sourceRoot":"","sources":["../../../../src/vanillajs/auth/handlers/MessageHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { AuthEvent } from \"../../types/index.js\";\nimport type { AuthResult } from \"../../types/index.js\";\nimport type {\n IframeMessage,\n AuthMessage,\n LoginAppMessage,\n ProcessedCivicAuthConfig,\n} from \"../types/AuthTypes.js\";\nimport { CivicAuthError, CivicAuthErrorCode } from \"../types/AuthTypes.js\";\nimport type { createLogger } from \"../../utils/logger.js\";\nimport { createLogger as createLoggerFn } from \"../../utils/logger.js\";\nimport { IframeManager } from \"@/vanillajs/iframe/IframeManager.js\";\n\nexport interface MessageHandlerConfig {\n config: ProcessedCivicAuthConfig;\n logger: ReturnType<typeof createLogger>;\n iframeElement?: HTMLIFrameElement;\n onAuthSuccess: (result: AuthResult) => void;\n onAuthError: (error: Error) => void;\n onPopupFailure: (failedUrl?: string) => void;\n onBrowserCorsFailsSilently: (failedUrl?: string) => Promise<void>;\n cleanup: () => void;\n}\n\n/**\n * MessageHandler - Handles postMessage communication and authentication flow logic\n * Processes messages from iframe, validates origins, and manages auth state transitions\n */\nexport class MessageHandler {\n private config: ProcessedCivicAuthConfig;\n private logger = createLoggerFn(\"message-handler\");\n private iframeElement?: HTMLIFrameElement;\n private onAuthSuccess: (result: AuthResult) => void;\n private onAuthError: (error: Error) => void;\n private onPopupFailure: (failedUrl?: string) => void;\n private onBrowserCorsFailsSilently: (failedUrl?: string) => Promise<void> =\n () => {\n return Promise.resolve(); // No-op by default, can be overridden\n };\n private cleanup: () => void;\n\n // Backend integration - custom expected origin\n private customExpectedOrigin?: string;\n\n constructor(handlerConfig: MessageHandlerConfig) {\n this.config = handlerConfig.config;\n this.iframeElement = handlerConfig.iframeElement;\n this.onAuthSuccess = handlerConfig.onAuthSuccess;\n this.onAuthError = handlerConfig.onAuthError;\n this.onPopupFailure = handlerConfig.onPopupFailure;\n this.onBrowserCorsFailsSilently = handlerConfig.onBrowserCorsFailsSilently;\n this.cleanup = handlerConfig.cleanup;\n }\n\n /**\n * Updates the iframe element reference used for message validation.\n *\n * This method allows updating the iframe element after the MessageHandler\n * has been instantiated, which is useful when the iframe is created\n * dynamically after the handler setup.\n *\n * @param iframeElement - The new iframe element to associate with this handler\n */\n public updateIframeElement(iframeElement: HTMLIFrameElement): void {\n this.iframeElement = iframeElement;\n }\n\n /**\n * Sets a custom expected origin for backend integration.\n *\n * This allows the MessageHandler to accept messages from a custom backend\n * origin instead of the default OAuth server origin.\n *\n * @param customLoginUrl - The custom login URL to derive the origin from\n */\n public setCustomExpectedOrigin(customLoginUrl: string): void {\n this.customExpectedOrigin = new URL(customLoginUrl).origin;\n this.logger.info(\"🔗 Custom expected origin set for backend integration\", {\n customExpectedOrigin: this.customExpectedOrigin,\n customLoginUrl,\n });\n }\n\n /**\n * Clears the custom expected origin and returns to OAuth server origin.\n */\n public clearCustomExpectedOrigin(): void {\n this.customExpectedOrigin = undefined;\n this.logger.info(\n \"🔗 Custom expected origin cleared, returning to OAuth server origin\",\n );\n }\n\n /**\n * Main message handler for processing postMessage events.\n *\n * Validates message origin and source, then routes valid messages to\n * appropriate handlers. This is the entry point for all iframe communication.\n *\n * @param event - The MessageEvent received from the iframe or other sources\n */\n public handleMessage = (event: MessageEvent): void => {\n // Use custom origin if set (for backend integration), otherwise use OAuth server origin\n const expectedOrigin =\n this.customExpectedOrigin ||\n new URL(this.config.oauthServerBaseUrl).origin;\n this.logIncomingMessage(event, expectedOrigin);\n\n if (!this.isValidMessageSource(event, expectedOrigin)) {\n return;\n }\n\n this.handleValidMessage(event);\n };\n\n /**\n * Logs incoming message details for debugging purposes.\n *\n * Provides comprehensive logging of message properties including origin,\n * source validation, and iframe state for troubleshooting communication issues.\n *\n * @param event - The MessageEvent to log\n * @param expectedOrigin - The expected origin for comparison\n */\n private logIncomingMessage(\n event: MessageEvent,\n expectedOrigin: string,\n ): void {\n this.logger.debug(\"Global window received message:\", {\n data: event.data,\n origin: event.origin,\n sourceProvided: !!event.source,\n iframeContentWindow: this.iframeElement?.contentWindow,\n expectedIframeOrigin: expectedOrigin,\n });\n }\n\n /**\n * Validates that a message comes from the expected origin and source.\n *\n * Performs security checks to ensure messages are only processed from\n * the configured OAuth server origin and the designated iframe element.\n *\n * @param event - The MessageEvent to validate\n * @param expectedOrigin - The expected origin URL for the message\n * @returns True if the message source and origin are valid, false otherwise\n */\n private isValidMessageSource(\n event: MessageEvent,\n expectedOrigin: string,\n ): boolean {\n // Check if message is from the iframe source\n const isValidSource = event.source === this.iframeElement?.contentWindow;\n\n // Build list of allowed origins\n const allowedOrigins = [expectedOrigin];\n\n // Add the actual iframe origin (to handle redirects)\n if (this.iframeElement?.src) {\n try {\n const actualIframeOrigin = new URL(this.iframeElement.src).origin;\n allowedOrigins.push(actualIframeOrigin);\n } catch {\n // ignore URL parsing errors\n }\n }\n\n if (this.config.oauthServerBaseUrl) {\n allowedOrigins.push(new URL(this.config.oauthServerBaseUrl).origin);\n }\n\n // Add the client app's own origin (same-origin) for messages sent after token exchange\n // This is needed when the iframe navigates to the client app's callback URL\n const clientOrigin = window.location.origin;\n if (!allowedOrigins.includes(clientOrigin)) {\n allowedOrigins.push(clientOrigin);\n }\n\n // Add common development login app origins for localhost\n const expectedUrl = new URL(expectedOrigin);\n if (expectedUrl.hostname === \"localhost\") {\n // For localhost, also allow common development ports\n allowedOrigins.push(\"http://localhost:3004\"); // default login-app port\n allowedOrigins.push(\"http://localhost:3001\"); // auth server port\n }\n\n const isValidOrigin = allowedOrigins.includes(event.origin);\n\n if (!isValidOrigin) {\n this.logger.warn(\"Ignored message from unexpected origin.\", {\n receivedOrigin: event.origin,\n expectedOrigin,\n allowedOrigins,\n iframeSrc: this.iframeElement?.src,\n });\n }\n\n if (!isValidSource) {\n this.logger.warn(\"Ignored message from unexpected source.\", {\n isSourceProvided: !!event.source,\n isIframeContentWindowAvailable: !!this.iframeElement?.contentWindow,\n iframeSrc: this.iframeElement?.src,\n });\n }\n\n return isValidOrigin && isValidSource;\n }\n\n /**\n * Processes messages that have passed origin and source validation.\n *\n * Routes validated messages to specific handlers based on message type,\n * including civicloginApp messages, iframe resizer messages, and standard auth messages.\n *\n * @param event - The validated MessageEvent to process\n */\n private handleValidMessage(event: MessageEvent): void {\n this.logger.info(\n \"Message from configured iframe source and origin received\",\n {\n data: event.data,\n iframeSrc: this.iframeElement?.src,\n },\n );\n\n const message = event.data as IframeMessage;\n\n this.logger.debug(\"Processing iframe message\", {\n messageType: typeof message,\n hasType: message && typeof message === \"object\" && \"type\" in message,\n hasSource: message && typeof message === \"object\" && \"source\" in message,\n messageKeys:\n message && typeof message === \"object\" ? Object.keys(message) : [],\n rawData: message,\n });\n\n // Handle civicloginApp messages\n if (this.isCivicLoginAppMessage(message)) {\n this.handleCivicLoginAppMessage(message);\n return;\n }\n\n // Handle iframe resizer messages\n if (this.isIframeResizerMessage(message)) {\n this.handleIframeResizerMessage(message);\n return;\n }\n\n // Handle standard auth messages\n this.handleStandardAuthMessage(message);\n }\n\n /**\n * Type guard to identify civicloginApp messages.\n *\n * Checks if a message object has the structure and source property\n * that identifies it as coming from the civicloginApp.\n *\n * @param message - The message object to check\n * @returns True if the message is a LoginAppMessage, false otherwise\n */\n private isCivicLoginAppMessage(message: unknown): message is LoginAppMessage {\n return (\n message !== null &&\n typeof message === \"object\" &&\n \"source\" in message &&\n (message as Record<string, unknown>).source === \"civicloginApp\"\n );\n }\n\n /**\n * Handles messages originating from the civicloginApp.\n *\n * Processes various civicloginApp message types including authentication errors,\n * popup failures, design updates, and other app-specific communications.\n * Validates client ID matches before processing.\n *\n * @param message - The validated civicloginApp message to process\n */\n private handleCivicLoginAppMessage(message: LoginAppMessage): void {\n this.logger.info(\"Received civicloginApp message\", {\n type: message.type,\n clientId: message.clientId,\n data: message.data,\n });\n\n // Validate clientId matches our config\n if (\n message.clientId !== this.config.clientId &&\n this.config.loginUrl === undefined\n ) {\n this.logger.warn(\"civicloginApp message clientId mismatch\", {\n received: message.clientId,\n expected: this.config.clientId,\n });\n return;\n }\n\n switch (message.type) {\n case \"auth_error\":\n case \"auth_error_try_again\":\n this.handleCivicLoginAppError(message);\n break;\n case \"generatePopupFailed\":\n this.handlePopupFailure(message);\n break;\n case \"browserCorsFailsSilently\":\n this.handleBrowserCorsFailsSilently(message);\n break;\n case \"design\":\n this.logger.debug(\"civicloginApp design message\", {\n data: message.data,\n });\n break;\n case \"auth_success_early\":\n this.logger.info(\"civicloginApp auth success early message\", {\n data: message.data,\n });\n this.handleAuthSuccessEarly(message);\n break;\n case \"auth_success\":\n this.logger.info(\"civicloginApp auth success message\", {\n data: message.data,\n });\n\n // Dispatch early auth success event for immediate modal closing\n\n // Still handle auth success normally (for callback processing)\n this.handleAuthSuccess({\n type: \"auth_success\",\n detail: \"Authentication successful\",\n data: message.data,\n });\n break;\n default:\n this.handleUnknownCivicLoginAppMessage(message);\n break;\n }\n }\n\n /**\n * Handles auth success early messages from civicloginApp.\n *\n * Processes auth_success_early messages, emits success events,\n * and triggers the success callback with authentication results.\n *\n * @param message - The civicloginApp auth success early message to process\n */\n\n private handleAuthSuccessEarly(message: LoginAppMessage): void {\n this.logger.info(\"civicloginApp auth success early message\", {\n data: message.data,\n });\n\n const earlySuccessEvent = new CustomEvent(\"civic-auth-success-early\", {\n detail: {\n clientId: message.clientId,\n data: message.data,\n },\n });\n window.dispatchEvent(earlySuccessEvent);\n }\n\n /**\n * Handles authentication error messages from civicloginApp.\n *\n * Processes auth_error and auth_error_try_again messages, creates\n * appropriate error objects, emits error events, and triggers cleanup.\n *\n * @param message - The civicloginApp error message to process\n */\n private handleCivicLoginAppError(message: LoginAppMessage): void {\n this.logger.error(\"civicloginApp authentication error\", {\n type: message.type,\n data: message.data,\n });\n\n const error = new CivicAuthError(\n `Login app error: ${message.type}`,\n CivicAuthErrorCode.INVALID_MESSAGE,\n );\n\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: error.message,\n error: message.data,\n });\n\n this.onAuthError(error);\n this.cleanup();\n }\n\n /**\n * Handle the case where we know in advance that the browser will not prompt the user to open\n * a popup and will fail silently instead. We want to handle this case gracefully by switching to redirect\n * mode if the iframe is in modal display mode. This will be done when the auth flow actually starts\n * @param message\n */\n private handleBrowserCorsFailsSilently(message: LoginAppMessage): void {\n const failedUrl = (message.data as Record<string, unknown> | undefined)\n ?.url as string | undefined;\n this.logger.warn(\"civicloginApp browser CORS fail silently\", {\n failedUrl,\n config: this.config,\n autoRedirect: this.config.autoRedirect,\n });\n if (\n this.config.displayMode === \"iframe\" &&\n this.config.iframeDisplayMode === \"modal\" &&\n this.config.autoRedirect !== false && // Add this check\n failedUrl\n ) {\n IframeManager.handleBrowserCorsFailsSilently(failedUrl);\n this.onBrowserCorsFailsSilently(failedUrl);\n }\n }\n /**\n * Handles popup generation failure messages from civicloginApp.\n *\n * Processes generatePopupFailed messages, extracts the failed URL,\n * emits appropriate events, and triggers the popup failure callback\n * to enable fallback authentication methods.\n *\n * @param message - The civicloginApp popup failure message to process\n */\n private handlePopupFailure(message: LoginAppMessage): void {\n this.logger.warn(\"civicloginApp popup generation failed\", {\n data: message.data,\n });\n\n const failedUrl = (message.data as Record<string, unknown> | undefined)\n ?.url as string | undefined;\n if (failedUrl) {\n this.logger.info(\"Popup failed for URL, considering fallback options\", {\n failedUrl,\n displayMode: this.config.displayMode,\n });\n\n this.config.events?.emit(AuthEvent.URL_CHANGE, {\n detail: \"Popup blocked by browser - switching to redirect mode\",\n url: failedUrl,\n source: \"login_app\",\n failedUrl,\n error: {\n type: \"popup_blocked\",\n failedUrl,\n suggestion:\n \"The browser blocked a popup window. Redirecting to complete authentication in a new page.\",\n },\n });\n }\n\n this.onPopupFailure(failedUrl);\n }\n\n /**\n * Handles unknown or unrecognized civicloginApp message types.\n *\n * Provides fallback handling for unexpected message types, with special\n * logic to detect potential success messages that don't match standard types.\n *\n * @param message - The unrecognized civicloginApp message to process\n */\n private handleUnknownCivicLoginAppMessage(message: LoginAppMessage): void {\n this.logger.debug(\"Unhandled civicloginApp message type\", {\n type: message.type,\n data: message.data,\n });\n\n // Check if this might be a success message with a different type\n if (message.type && message.type.toLowerCase().includes(\"success\")) {\n this.logger.info(\"Potential success message from civicloginApp\", {\n type: message.type,\n data: message.data,\n });\n\n this.handleAuthSuccess({\n type: \"auth_success\",\n detail: `civicloginApp success: ${message.type}`,\n data: message.data,\n });\n }\n }\n\n /**\n * Type guard to identify iframe resizer messages.\n *\n * Checks if a message is related to iframe resizing functionality,\n * including both civic-specific resize messages and iFrameResizerChild messages.\n *\n * @param message - The message object to check\n * @returns True if the message is an iframe resizer message, false otherwise\n */\n private isIframeResizerMessage(message: unknown): boolean {\n return (\n (message !== null &&\n typeof message === \"object\" &&\n \"type\" in message &&\n ((message as Record<string, unknown>).type === \"civic-iframe-resize\" ||\n (message as Record<string, unknown>).type ===\n \"civic-iframe-ready\")) ||\n (typeof message === \"string\" && message.includes(\"iFrameResizerChild\"))\n );\n }\n\n /**\n * Handles iframe resizer messages for dynamic iframe sizing.\n *\n * Processes messages related to iframe resizing, including height adjustments\n * and ready state notifications from the iframe resizer library.\n *\n * @param message - The iframe resizer message to process\n */\n private handleIframeResizerMessage(message: unknown): void {\n if (typeof message === \"string\") {\n this.logger.debug(\"Received iframe resizer child message\", { message });\n } else if (message && typeof message === \"object\" && message !== null) {\n const messageObj = message as Record<string, unknown>;\n this.logger.debug(\"Received iframe resizer message\", {\n type: messageObj.type,\n height: messageObj.height,\n });\n }\n }\n\n /**\n * Handles standard authentication messages.\n *\n * Processes auth_success and auth_error messages that follow the standard\n * authentication message format, routing them to appropriate success or error handlers.\n *\n * @param message - The standard auth message to process\n */\n private handleStandardAuthMessage(message: unknown): void {\n const messageObj =\n message && typeof message === \"object\" && message !== null\n ? (message as Record<string, unknown>)\n : null;\n const messageType = messageObj?.type;\n\n switch (messageType) {\n case \"auth_success\":\n this.handleAuthSuccess(message as AuthMessage);\n break;\n case \"auth_error\":\n this.handleAuthError(message as AuthMessage);\n break;\n default:\n // Check if this is a calculateSubFramePositioning message (expected and harmless)\n if (messageObj?.command === \"calculateSubFramePositioning\") {\n this.logger.debug(\"Received iframe positioning message (expected)\", {\n command: messageObj.command,\n hasSubFrameData: !!messageObj.subFrameData,\n });\n } else {\n this.logger.debug(\n \"Message from iframe did not match expected types (auth_success, auth_error, civicloginApp, iframe-resizer)\",\n {\n data: message,\n messageType: typeof message,\n hasType: messageObj?.type ?? \"none\",\n messageKeys: messageObj ? Object.keys(messageObj) : [],\n },\n );\n }\n }\n }\n\n /**\n * Handles successful authentication completion.\n *\n * Processes authentication success messages, emits success events,\n * triggers the success callback with authentication results, and performs cleanup.\n *\n * @param data - The authentication success message containing result data\n */\n private handleAuthSuccess(data: AuthMessage): void {\n this.config.events?.emit(AuthEvent.SIGN_IN_COMPLETE, {\n detail: \"Success signal received via postMessage\",\n data,\n });\n this.onAuthSuccess((data?.data as AuthResult) || {});\n this.cleanup();\n }\n\n /**\n * Handles authentication errors.\n *\n * Processes authentication error messages, creates appropriate error objects,\n * emits error events, triggers the error callback, and performs cleanup.\n *\n * @param data - The authentication error message containing error details\n */\n private handleAuthError(data: AuthMessage): void {\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Error signal received via postMessage\",\n error: data,\n });\n\n const error = new CivicAuthError(\n data?.detail || \"Error signal received via postMessage\",\n CivicAuthErrorCode.INVALID_MESSAGE,\n );\n\n this.onAuthError(error);\n this.cleanup();\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"PopupHandler.d.ts","sourceRoot":"","sources":["../../../../src/vanillajs/auth/handlers/PopupHandler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EACV,wBAAwB,EAEzB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG1D,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,wBAAwB,CAAC;IACjC,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IACxC,aAAa,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAC5C,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACpC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,KAAK,CAAC,CAAgB;IAC9B,OAAO,CAAC,kBAAkB,CAAC,CAAS;IACpC,OAAO,CAAC,aAAa,CAA+B;IACpD,OAAO,CAAC,WAAW,CAAyB;IAC5C,OAAO,CAAC,OAAO,CAAa;gBAEhB,aAAa,EAAE,kBAAkB;IAQ7C;;;;;;;;;OASG;IACU,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoFjE;;;;;;;;OAQG;IACH,OAAO,CAAC,sBAAsB;IAQ9B;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,YAAY;IA2FpB;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IAkB1B;;;;;;;;OAQG;IACH,OAAO,CAAC,gBAAgB;IA0BxB;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAsBzB;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IAsB1B;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;CAuB3B"}
1
+ {"version":3,"file":"PopupHandler.d.ts","sourceRoot":"","sources":["../../../../src/vanillajs/auth/handlers/PopupHandler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EACV,wBAAwB,EAEzB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG1D,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,wBAAwB,CAAC;IACjC,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IACxC,aAAa,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAC5C,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACpC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,KAAK,CAAC,CAAgB;IAC9B,OAAO,CAAC,kBAAkB,CAAC,CAAS;IACpC,OAAO,CAAC,aAAa,CAA+B;IACpD,OAAO,CAAC,WAAW,CAAyB;IAC5C,OAAO,CAAC,OAAO,CAAa;gBAEhB,aAAa,EAAE,kBAAkB;IAQ7C;;;;;;;;;OASG;IACU,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsFjE;;;;;;;;OAQG;IACH,OAAO,CAAC,sBAAsB;IAQ9B;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,YAAY;IA2FpB;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IAkB1B;;;;;;;;OAQG;IACH,OAAO,CAAC,gBAAgB;IA0BxB;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAsBzB;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IAsB1B;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;CAuB3B"}
@@ -63,8 +63,10 @@ export class PopupHandler {
63
63
  this.logger.warn("🚫 Safari popup was immediately closed (likely blocked)");
64
64
  const error = new PopupError("Safari blocked popup window");
65
65
  if (this.config.events) {
66
- this.config.events.emit(AuthEvent.SIGN_IN_ERROR, {
66
+ this.config.events.emit(AuthEvent.URL_CHANGE, {
67
67
  detail: error.message,
68
+ url: fullAuthUrl,
69
+ source: "login",
68
70
  error,
69
71
  });
70
72
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PopupHandler.js","sourceRoot":"","sources":["../../../../src/vanillajs/auth/handlers/PopupHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { AuthEvent } from \"../../types/index.js\";\nimport type { AuthResult } from \"../../types/index.js\";\nimport type {\n ProcessedCivicAuthConfig,\n AuthMessage,\n} from \"../types/AuthTypes.js\";\nimport { CivicAuthError, CivicAuthErrorCode } from \"../types/AuthTypes.js\";\nimport { PopupError } from \"../../../services/types.js\";\nimport type { createLogger } from \"../../utils/logger.js\";\nimport { createLogger as createLoggerFn } from \"../../utils/logger.js\";\n\nexport interface PopupHandlerConfig {\n config: ProcessedCivicAuthConfig;\n logger: ReturnType<typeof createLogger>; // Keep for interface compatibility but won't use\n onAuthSuccess: (result: AuthResult) => void;\n onAuthError: (error: Error) => void;\n cleanup: () => void;\n}\n\nexport class PopupHandler {\n private config: ProcessedCivicAuthConfig;\n private logger = createLoggerFn(\"popup\"); // Create own logger\n private popup?: Window | null;\n private popupCheckInterval?: number;\n private onAuthSuccess: (result: AuthResult) => void;\n private onAuthError: (error: Error) => void;\n private cleanup: () => void;\n\n constructor(handlerConfig: PopupHandlerConfig) {\n this.config = handlerConfig.config;\n // Don't use handlerConfig.logger - use our own logger instead\n this.onAuthSuccess = handlerConfig.onAuthSuccess;\n this.onAuthError = handlerConfig.onAuthError;\n this.cleanup = handlerConfig.cleanup;\n }\n\n /**\n * Initiates authentication flow using a popup window.\n *\n * Opens a new browser window/tab for authentication, handles browser compatibility\n * (especially Safari), and sets up monitoring for the authentication process.\n *\n * @param fullAuthUrl - The complete authentication URL to open in the popup\n * @throws {PopupError} When popup window cannot be opened (blocked by browser)\n * @returns Promise that resolves when popup setup is complete\n */\n public async handleNewTabAuth(fullAuthUrl: string): Promise<void> {\n this.logger.info(\"🚀 Starting new tab authentication\", {\n url: fullAuthUrl,\n userAgent: navigator.userAgent,\n isSafari:\n /Safari/.test(navigator.userAgent) &&\n !/Chrome/.test(navigator.userAgent),\n });\n\n try {\n // For Safari, use specific window features that work better\n const isSafari =\n /Safari/.test(navigator.userAgent) &&\n !/Chrome/.test(navigator.userAgent);\n const windowFeatures = isSafari\n ? \"width=500,height=600,scrollbars=yes,resizable=yes\"\n : \"\";\n\n const popupWindow = isSafari\n ? window.open(fullAuthUrl, \"_blank\", windowFeatures)\n : window.open(fullAuthUrl, \"_blank\");\n\n this.logger.info(\"📱 Popup window attempt result\", {\n popupWindow: popupWindow,\n popupWindowType: typeof popupWindow,\n isNull: popupWindow === null,\n isUndefined: popupWindow === undefined,\n windowFeatures: isSafari ? windowFeatures : \"none specified\",\n isSafari,\n });\n\n if (!popupWindow) {\n throw new PopupError(\n \"Failed to open popup window - likely blocked by browser\",\n );\n }\n\n // Additional Safari-specific check: Safari might return a window object but still block it\n if (isSafari) {\n // Give Safari a moment to potentially close the popup if it was blocked\n setTimeout(() => {\n if (popupWindow.closed) {\n this.logger.warn(\n \"🚫 Safari popup was immediately closed (likely blocked)\",\n );\n const error = new PopupError(\"Safari blocked popup window\");\n if (this.config.events) {\n this.config.events.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: error.message,\n error,\n });\n }\n this.onAuthError(error);\n return;\n }\n }, 100);\n }\n\n this.logger.info(\"✅ Popup window opened successfully\", {\n popupWindow: !!popupWindow,\n popupClosed: popupWindow.closed,\n popupLocation: this.getPopupLocationSafely(popupWindow),\n });\n\n // Set up popup monitoring\n this.monitorPopup(popupWindow);\n } catch (error) {\n this.logger.error(\"❌ Popup window creation failed\", {\n error: error,\n errorType: error instanceof PopupError ? \"PopupError\" : \"Other\",\n });\n\n if (error instanceof PopupError) {\n // Re-throw PopupError to be caught by the main authentication flow\n throw error;\n } else {\n // Wrap other errors as PopupError\n throw new PopupError(\n `window.open has thrown: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n\n /**\n * Safely retrieves the current location of a popup window.\n *\n * Attempts to access the popup's location.href property, handling cross-origin\n * access restrictions gracefully by returning a descriptive message instead of throwing.\n *\n * @param popup - The popup window to get location from\n * @returns The popup's URL or a descriptive message if access is restricted\n */\n private getPopupLocationSafely(popup: Window): string {\n try {\n return popup.location.href;\n } catch {\n return \"cross-origin (cannot access)\";\n }\n }\n\n /**\n * Monitors a popup window for authentication results and handles communication.\n *\n * This method sets up a postMessage listener to receive authentication results from the popup\n * and periodically checks if the popup has been closed. It handles success/error messages\n * and automatically cleans up resources when the popup closes or times out.\n *\n * @param popup - The popup window to monitor for authentication completion\n *\n * @remarks\n * - Monitors popup for up to 5 minutes (300 checks at 1-second intervals)\n * - Listens for 'auth_success' and 'auth_error' message types from the popup\n * - Automatically removes event listeners and resolves/rejects promises when done\n * - Logs detailed debugging information throughout the monitoring process\n *\n * @private\n */\n private monitorPopup(popup: Window): void {\n this.logger.info(\"👀 Starting popup monitoring\");\n\n let checkCount = 0;\n const maxChecks = 300; // 5 minutes at 1 second intervals\n let popupMessageHandler: ((event: MessageEvent) => void) | null = null;\n\n // Set up postMessage listener for popup communication\n popupMessageHandler = (event: MessageEvent) => {\n this.logger.debug(\"📨 Received message from popup\", {\n origin: event.origin,\n data: event.data,\n source: event.source === popup,\n messageType: event.data?.type,\n isFromTargetPopup: event.source === popup,\n });\n\n // Verify the message is from our popup\n if (event.source !== popup) {\n this.logger.debug(\"🚫 Ignoring message from different source\", {\n expectedSource: popup,\n actualSource: event.source,\n });\n return;\n }\n\n const message = event.data;\n if (message && typeof message === \"object\" && message.type) {\n this.logger.info(\"✅ Valid popup message received\", {\n type: message.type,\n detail: message.detail,\n hasData: !!message.data,\n });\n\n switch (message.type) {\n case \"auth_success\":\n this.handlePopupSuccess(message, popupMessageHandler);\n break;\n case \"auth_error\":\n this.handlePopupError(message, popupMessageHandler);\n break;\n default:\n this.logger.debug(\"🤷 Unknown message type from popup\", {\n type: message.type,\n fullMessage: message,\n });\n }\n } else {\n this.logger.debug(\"📨 Non-auth message received from popup\", {\n messageType: typeof message,\n message,\n });\n }\n };\n\n // Add the message listener\n window.addEventListener(\"message\", popupMessageHandler);\n this.logger.info(\"📡 Added popup message listener\", {\n popupWindowExists: !!popup,\n popupClosed: popup.closed,\n });\n\n const checkClosed = () => {\n checkCount++;\n this.logger.debug(`🔍 Popup check #${checkCount}`, {\n closed: popup.closed,\n location: this.getPopupLocationSafely(popup),\n maxChecks,\n });\n\n if (popup.closed) {\n this.handlePopupClosed(popupMessageHandler);\n return;\n }\n\n if (checkCount >= maxChecks) {\n this.handlePopupTimeout(popupMessageHandler);\n return;\n }\n\n // Check popup location for redirect (this is now mainly for debugging)\n this.checkPopupLocation(popup);\n\n // Continue monitoring\n setTimeout(checkClosed, 1000);\n };\n\n // Start monitoring\n setTimeout(checkClosed, 1000);\n }\n\n /**\n * Handles successful authentication completion from the popup.\n *\n * Processes the authentication success message received from the popup window,\n * emits success events, triggers the success callback, and performs cleanup.\n *\n * @param message - The authentication message containing success data\n * @param popupMessageHandler - The message event handler to clean up, or null if none exists\n */\n private handlePopupSuccess(\n message: AuthMessage,\n popupMessageHandler: ((event: MessageEvent) => void) | null,\n ): void {\n this.logger.info(\"🎉 Popup authentication successful\");\n this.config.events?.emit(AuthEvent.SIGN_IN_COMPLETE, {\n detail: \"Popup authentication successful\",\n data: message.data,\n });\n this.onAuthSuccess(message.data || {});\n this.cleanup();\n\n // Clean up message listener\n if (popupMessageHandler) {\n window.removeEventListener(\"message\", popupMessageHandler);\n }\n }\n\n /**\n * Handles authentication errors received from the popup.\n *\n * Processes error messages from the popup window, emits error events,\n * creates appropriate CivicAuthError instances, and performs cleanup.\n *\n * @param message - The authentication message containing error details\n * @param popupMessageHandler - The message event handler to clean up, or null if none exists\n */\n private handlePopupError(\n message: AuthMessage,\n popupMessageHandler: ((event: MessageEvent) => void) | null,\n ): void {\n this.logger.error(\"❌ Popup authentication failed\", {\n detail: message.detail,\n });\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: message.detail || \"Popup authentication failed\",\n error: message.error,\n });\n\n const error = new CivicAuthError(\n message.detail || \"Popup authentication failed\",\n CivicAuthErrorCode.INVALID_MESSAGE,\n );\n\n this.onAuthError(error);\n this.cleanup();\n\n // Clean up message listener\n if (popupMessageHandler) {\n window.removeEventListener(\"message\", popupMessageHandler);\n }\n }\n\n /**\n * Handles the scenario when the authentication popup is closed by the user.\n * This method is called when the popup window is detected as closed during monitoring.\n * It emits an error event, creates an appropriate error, and performs cleanup.\n *\n * @param popupMessageHandler - The message event handler to clean up, or null if none exists\n */\n private handlePopupClosed(\n popupMessageHandler: ((event: MessageEvent) => void) | null,\n ): void {\n this.logger.warn(\"🔒 Popup was closed by user\");\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Authentication cancelled by user (popup closed)\",\n });\n\n const error = new CivicAuthError(\n \"Authentication cancelled by user\",\n CivicAuthErrorCode.USER_CANCELLED,\n );\n\n this.onAuthError(error);\n this.cleanup();\n\n // Clean up message listener\n if (popupMessageHandler) {\n window.removeEventListener(\"message\", popupMessageHandler);\n }\n }\n\n /**\n * Handles authentication timeout scenarios.\n *\n * Called when the popup monitoring reaches its maximum time limit without\n * receiving authentication results. Emits timeout events, creates timeout errors,\n * and performs cleanup operations.\n *\n * @param popupMessageHandler - The message event handler to clean up, or null if none exists\n */\n private handlePopupTimeout(\n popupMessageHandler: ((event: MessageEvent) => void) | null,\n ): void {\n this.logger.warn(\"⏰ Popup monitoring timeout reached\");\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Authentication timeout - popup monitoring stopped\",\n });\n\n const error = new CivicAuthError(\n \"Authentication timeout\",\n CivicAuthErrorCode.AUTH_PROCESS_TIMEOUT,\n );\n\n this.onAuthError(error);\n this.cleanup();\n\n // Clean up message listener\n if (popupMessageHandler) {\n window.removeEventListener(\"message\", popupMessageHandler);\n }\n }\n\n /**\n * Monitors the popup's location for redirect changes.\n *\n * Attempts to check if the popup has redirected to the callback URL, which\n * indicates the authentication flow has progressed. Handles cross-origin\n * access restrictions gracefully by catching and logging access errors.\n *\n * @param popup - The popup window to monitor for location changes\n */\n private checkPopupLocation(popup: Window): void {\n try {\n const popupLocation = popup.location.href;\n this.logger.debug(\"📍 Popup location accessible\", {\n location: popupLocation,\n startsWithRedirect: popupLocation.startsWith(this.config.redirectUrl),\n });\n\n if (popupLocation.startsWith(this.config.redirectUrl)) {\n this.logger.info(\"🎯 Popup redirected to callback URL\", {\n location: popupLocation,\n });\n // The callback page should send us a postMessage, so we just wait for that\n }\n } catch (error) {\n // Expected when popup is on different origin\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n this.logger.debug(\"🔒 Cannot access popup location (cross-origin)\", {\n error: errorMessage,\n });\n }\n }\n}\n"]}
1
+ {"version":3,"file":"PopupHandler.js","sourceRoot":"","sources":["../../../../src/vanillajs/auth/handlers/PopupHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { AuthEvent } from \"../../types/index.js\";\nimport type { AuthResult } from \"../../types/index.js\";\nimport type {\n ProcessedCivicAuthConfig,\n AuthMessage,\n} from \"../types/AuthTypes.js\";\nimport { CivicAuthError, CivicAuthErrorCode } from \"../types/AuthTypes.js\";\nimport { PopupError } from \"../../../services/types.js\";\nimport type { createLogger } from \"../../utils/logger.js\";\nimport { createLogger as createLoggerFn } from \"../../utils/logger.js\";\n\nexport interface PopupHandlerConfig {\n config: ProcessedCivicAuthConfig;\n logger: ReturnType<typeof createLogger>; // Keep for interface compatibility but won't use\n onAuthSuccess: (result: AuthResult) => void;\n onAuthError: (error: Error) => void;\n cleanup: () => void;\n}\n\nexport class PopupHandler {\n private config: ProcessedCivicAuthConfig;\n private logger = createLoggerFn(\"popup\"); // Create own logger\n private popup?: Window | null;\n private popupCheckInterval?: number;\n private onAuthSuccess: (result: AuthResult) => void;\n private onAuthError: (error: Error) => void;\n private cleanup: () => void;\n\n constructor(handlerConfig: PopupHandlerConfig) {\n this.config = handlerConfig.config;\n // Don't use handlerConfig.logger - use our own logger instead\n this.onAuthSuccess = handlerConfig.onAuthSuccess;\n this.onAuthError = handlerConfig.onAuthError;\n this.cleanup = handlerConfig.cleanup;\n }\n\n /**\n * Initiates authentication flow using a popup window.\n *\n * Opens a new browser window/tab for authentication, handles browser compatibility\n * (especially Safari), and sets up monitoring for the authentication process.\n *\n * @param fullAuthUrl - The complete authentication URL to open in the popup\n * @throws {PopupError} When popup window cannot be opened (blocked by browser)\n * @returns Promise that resolves when popup setup is complete\n */\n public async handleNewTabAuth(fullAuthUrl: string): Promise<void> {\n this.logger.info(\"🚀 Starting new tab authentication\", {\n url: fullAuthUrl,\n userAgent: navigator.userAgent,\n isSafari:\n /Safari/.test(navigator.userAgent) &&\n !/Chrome/.test(navigator.userAgent),\n });\n\n try {\n // For Safari, use specific window features that work better\n const isSafari =\n /Safari/.test(navigator.userAgent) &&\n !/Chrome/.test(navigator.userAgent);\n const windowFeatures = isSafari\n ? \"width=500,height=600,scrollbars=yes,resizable=yes\"\n : \"\";\n\n const popupWindow = isSafari\n ? window.open(fullAuthUrl, \"_blank\", windowFeatures)\n : window.open(fullAuthUrl, \"_blank\");\n\n this.logger.info(\"📱 Popup window attempt result\", {\n popupWindow: popupWindow,\n popupWindowType: typeof popupWindow,\n isNull: popupWindow === null,\n isUndefined: popupWindow === undefined,\n windowFeatures: isSafari ? windowFeatures : \"none specified\",\n isSafari,\n });\n\n if (!popupWindow) {\n throw new PopupError(\n \"Failed to open popup window - likely blocked by browser\",\n );\n }\n\n // Additional Safari-specific check: Safari might return a window object but still block it\n if (isSafari) {\n // Give Safari a moment to potentially close the popup if it was blocked\n setTimeout(() => {\n if (popupWindow.closed) {\n this.logger.warn(\n \"🚫 Safari popup was immediately closed (likely blocked)\",\n );\n const error = new PopupError(\"Safari blocked popup window\");\n if (this.config.events) {\n this.config.events.emit(AuthEvent.URL_CHANGE, {\n detail: error.message,\n url: fullAuthUrl,\n source: \"login\",\n error,\n });\n }\n this.onAuthError(error);\n return;\n }\n }, 100);\n }\n\n this.logger.info(\"✅ Popup window opened successfully\", {\n popupWindow: !!popupWindow,\n popupClosed: popupWindow.closed,\n popupLocation: this.getPopupLocationSafely(popupWindow),\n });\n\n // Set up popup monitoring\n this.monitorPopup(popupWindow);\n } catch (error) {\n this.logger.error(\"❌ Popup window creation failed\", {\n error: error,\n errorType: error instanceof PopupError ? \"PopupError\" : \"Other\",\n });\n\n if (error instanceof PopupError) {\n // Re-throw PopupError to be caught by the main authentication flow\n throw error;\n } else {\n // Wrap other errors as PopupError\n throw new PopupError(\n `window.open has thrown: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n\n /**\n * Safely retrieves the current location of a popup window.\n *\n * Attempts to access the popup's location.href property, handling cross-origin\n * access restrictions gracefully by returning a descriptive message instead of throwing.\n *\n * @param popup - The popup window to get location from\n * @returns The popup's URL or a descriptive message if access is restricted\n */\n private getPopupLocationSafely(popup: Window): string {\n try {\n return popup.location.href;\n } catch {\n return \"cross-origin (cannot access)\";\n }\n }\n\n /**\n * Monitors a popup window for authentication results and handles communication.\n *\n * This method sets up a postMessage listener to receive authentication results from the popup\n * and periodically checks if the popup has been closed. It handles success/error messages\n * and automatically cleans up resources when the popup closes or times out.\n *\n * @param popup - The popup window to monitor for authentication completion\n *\n * @remarks\n * - Monitors popup for up to 5 minutes (300 checks at 1-second intervals)\n * - Listens for 'auth_success' and 'auth_error' message types from the popup\n * - Automatically removes event listeners and resolves/rejects promises when done\n * - Logs detailed debugging information throughout the monitoring process\n *\n * @private\n */\n private monitorPopup(popup: Window): void {\n this.logger.info(\"👀 Starting popup monitoring\");\n\n let checkCount = 0;\n const maxChecks = 300; // 5 minutes at 1 second intervals\n let popupMessageHandler: ((event: MessageEvent) => void) | null = null;\n\n // Set up postMessage listener for popup communication\n popupMessageHandler = (event: MessageEvent) => {\n this.logger.debug(\"📨 Received message from popup\", {\n origin: event.origin,\n data: event.data,\n source: event.source === popup,\n messageType: event.data?.type,\n isFromTargetPopup: event.source === popup,\n });\n\n // Verify the message is from our popup\n if (event.source !== popup) {\n this.logger.debug(\"🚫 Ignoring message from different source\", {\n expectedSource: popup,\n actualSource: event.source,\n });\n return;\n }\n\n const message = event.data;\n if (message && typeof message === \"object\" && message.type) {\n this.logger.info(\"✅ Valid popup message received\", {\n type: message.type,\n detail: message.detail,\n hasData: !!message.data,\n });\n\n switch (message.type) {\n case \"auth_success\":\n this.handlePopupSuccess(message, popupMessageHandler);\n break;\n case \"auth_error\":\n this.handlePopupError(message, popupMessageHandler);\n break;\n default:\n this.logger.debug(\"🤷 Unknown message type from popup\", {\n type: message.type,\n fullMessage: message,\n });\n }\n } else {\n this.logger.debug(\"📨 Non-auth message received from popup\", {\n messageType: typeof message,\n message,\n });\n }\n };\n\n // Add the message listener\n window.addEventListener(\"message\", popupMessageHandler);\n this.logger.info(\"📡 Added popup message listener\", {\n popupWindowExists: !!popup,\n popupClosed: popup.closed,\n });\n\n const checkClosed = () => {\n checkCount++;\n this.logger.debug(`🔍 Popup check #${checkCount}`, {\n closed: popup.closed,\n location: this.getPopupLocationSafely(popup),\n maxChecks,\n });\n\n if (popup.closed) {\n this.handlePopupClosed(popupMessageHandler);\n return;\n }\n\n if (checkCount >= maxChecks) {\n this.handlePopupTimeout(popupMessageHandler);\n return;\n }\n\n // Check popup location for redirect (this is now mainly for debugging)\n this.checkPopupLocation(popup);\n\n // Continue monitoring\n setTimeout(checkClosed, 1000);\n };\n\n // Start monitoring\n setTimeout(checkClosed, 1000);\n }\n\n /**\n * Handles successful authentication completion from the popup.\n *\n * Processes the authentication success message received from the popup window,\n * emits success events, triggers the success callback, and performs cleanup.\n *\n * @param message - The authentication message containing success data\n * @param popupMessageHandler - The message event handler to clean up, or null if none exists\n */\n private handlePopupSuccess(\n message: AuthMessage,\n popupMessageHandler: ((event: MessageEvent) => void) | null,\n ): void {\n this.logger.info(\"🎉 Popup authentication successful\");\n this.config.events?.emit(AuthEvent.SIGN_IN_COMPLETE, {\n detail: \"Popup authentication successful\",\n data: message.data,\n });\n this.onAuthSuccess(message.data || {});\n this.cleanup();\n\n // Clean up message listener\n if (popupMessageHandler) {\n window.removeEventListener(\"message\", popupMessageHandler);\n }\n }\n\n /**\n * Handles authentication errors received from the popup.\n *\n * Processes error messages from the popup window, emits error events,\n * creates appropriate CivicAuthError instances, and performs cleanup.\n *\n * @param message - The authentication message containing error details\n * @param popupMessageHandler - The message event handler to clean up, or null if none exists\n */\n private handlePopupError(\n message: AuthMessage,\n popupMessageHandler: ((event: MessageEvent) => void) | null,\n ): void {\n this.logger.error(\"❌ Popup authentication failed\", {\n detail: message.detail,\n });\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: message.detail || \"Popup authentication failed\",\n error: message.error,\n });\n\n const error = new CivicAuthError(\n message.detail || \"Popup authentication failed\",\n CivicAuthErrorCode.INVALID_MESSAGE,\n );\n\n this.onAuthError(error);\n this.cleanup();\n\n // Clean up message listener\n if (popupMessageHandler) {\n window.removeEventListener(\"message\", popupMessageHandler);\n }\n }\n\n /**\n * Handles the scenario when the authentication popup is closed by the user.\n * This method is called when the popup window is detected as closed during monitoring.\n * It emits an error event, creates an appropriate error, and performs cleanup.\n *\n * @param popupMessageHandler - The message event handler to clean up, or null if none exists\n */\n private handlePopupClosed(\n popupMessageHandler: ((event: MessageEvent) => void) | null,\n ): void {\n this.logger.warn(\"🔒 Popup was closed by user\");\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Authentication cancelled by user (popup closed)\",\n });\n\n const error = new CivicAuthError(\n \"Authentication cancelled by user\",\n CivicAuthErrorCode.USER_CANCELLED,\n );\n\n this.onAuthError(error);\n this.cleanup();\n\n // Clean up message listener\n if (popupMessageHandler) {\n window.removeEventListener(\"message\", popupMessageHandler);\n }\n }\n\n /**\n * Handles authentication timeout scenarios.\n *\n * Called when the popup monitoring reaches its maximum time limit without\n * receiving authentication results. Emits timeout events, creates timeout errors,\n * and performs cleanup operations.\n *\n * @param popupMessageHandler - The message event handler to clean up, or null if none exists\n */\n private handlePopupTimeout(\n popupMessageHandler: ((event: MessageEvent) => void) | null,\n ): void {\n this.logger.warn(\"⏰ Popup monitoring timeout reached\");\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: \"Authentication timeout - popup monitoring stopped\",\n });\n\n const error = new CivicAuthError(\n \"Authentication timeout\",\n CivicAuthErrorCode.AUTH_PROCESS_TIMEOUT,\n );\n\n this.onAuthError(error);\n this.cleanup();\n\n // Clean up message listener\n if (popupMessageHandler) {\n window.removeEventListener(\"message\", popupMessageHandler);\n }\n }\n\n /**\n * Monitors the popup's location for redirect changes.\n *\n * Attempts to check if the popup has redirected to the callback URL, which\n * indicates the authentication flow has progressed. Handles cross-origin\n * access restrictions gracefully by catching and logging access errors.\n *\n * @param popup - The popup window to monitor for location changes\n */\n private checkPopupLocation(popup: Window): void {\n try {\n const popupLocation = popup.location.href;\n this.logger.debug(\"📍 Popup location accessible\", {\n location: popupLocation,\n startsWithRedirect: popupLocation.startsWith(this.config.redirectUrl),\n });\n\n if (popupLocation.startsWith(this.config.redirectUrl)) {\n this.logger.info(\"🎯 Popup redirected to callback URL\", {\n location: popupLocation,\n });\n // The callback page should send us a postMessage, so we just wait for that\n }\n } catch (error) {\n // Expected when popup is on different origin\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n this.logger.debug(\"🔒 Cannot access popup location (cross-origin)\", {\n error: errorMessage,\n });\n }\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import type { AuthenticationEvents } from "../AuthenticationEvents.js";
2
- import type { DisplayMode as BaseDisplayMode, AuthStorage, FrameworkType } from "../../../types.js";
2
+ import type { DisplayMode as BaseDisplayMode, AuthStorage, FrameworkType, User } from "../../../types.js";
3
3
  import type { BackendEndpoints } from "../../../server/config.js";
4
4
  /**
5
5
  * Extended DisplayMode for VanillaJS that includes "embedded" option
@@ -122,6 +122,14 @@ export type CivicAuthClientConfig = {
122
122
  preloadIframe?: boolean;
123
123
  /** Whether to automatically switch to redirect mode when browser doesn't support iframe-based auth (defaults to true) */
124
124
  autoRedirect?: boolean;
125
+ /** URL to redirect to after successful login - defaults to the page that initiated login */
126
+ loginSuccessUrl?: string;
127
+ /** Initial user data to avoid backend calls during authentication state checks.
128
+ * - User object: user is authenticated
129
+ * - null: explicitly no user (skip backend checks)
130
+ * - undefined: unknown state (check backend)
131
+ */
132
+ initialUser?: User | null;
125
133
  } & ({
126
134
  /** OAuth client ID - required for standard OAuth flow */
127
135
  clientId: string;
@@ -166,6 +174,8 @@ export type ProcessedCivicAuthConfig = {
166
174
  events?: AuthenticationEvents;
167
175
  initialState?: string;
168
176
  framework?: FrameworkType;
177
+ loginSuccessUrl?: string;
178
+ initialUser?: User | null;
169
179
  } & ({
170
180
  /** OAuth client ID - required for standard OAuth flow */
171
181
  clientId: string;