@civic/auth 0.9.5 โ 0.9.6-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -1
- package/dist/nextjs/actions.d.ts +12 -0
- package/dist/nextjs/actions.d.ts.map +1 -0
- package/dist/nextjs/actions.js +26 -0
- package/dist/nextjs/actions.js.map +1 -0
- package/dist/nextjs/config.d.ts +2 -0
- package/dist/nextjs/config.d.ts.map +1 -1
- package/dist/nextjs/config.js +3 -2
- package/dist/nextjs/config.js.map +1 -1
- package/dist/nextjs/cookies.d.ts.map +1 -1
- package/dist/nextjs/cookies.js +45 -3
- package/dist/nextjs/cookies.js.map +1 -1
- package/dist/nextjs/hooks/useInitialAuthConfig.d.ts +31 -0
- package/dist/nextjs/hooks/useInitialAuthConfig.d.ts.map +1 -0
- package/dist/nextjs/hooks/useInitialAuthConfig.js +109 -0
- package/dist/nextjs/hooks/useInitialAuthConfig.js.map +1 -0
- package/dist/nextjs/index.d.ts +1 -0
- package/dist/nextjs/index.d.ts.map +1 -1
- package/dist/nextjs/index.js +13 -3
- package/dist/nextjs/index.js.map +1 -1
- package/dist/nextjs/providers/NextAuthProvider.d.ts +6 -7
- package/dist/nextjs/providers/NextAuthProvider.d.ts.map +1 -1
- package/dist/nextjs/providers/NextAuthProvider.js +19 -138
- package/dist/nextjs/providers/NextAuthProvider.js.map +1 -1
- package/dist/nextjs/providers/NextAuthProviderClient.d.ts +11 -0
- package/dist/nextjs/providers/NextAuthProviderClient.d.ts.map +1 -0
- package/dist/nextjs/providers/NextAuthProviderClient.js +62 -0
- package/dist/nextjs/providers/NextAuthProviderClient.js.map +1 -0
- package/dist/nextjs/providers/ServerUserContext.d.ts +2 -0
- package/dist/nextjs/providers/ServerUserContext.d.ts.map +1 -0
- package/dist/nextjs/providers/ServerUserContext.js +5 -0
- package/dist/nextjs/providers/ServerUserContext.js.map +1 -0
- package/dist/nextjs/routeHandler.d.ts.map +1 -1
- package/dist/nextjs/routeHandler.js +241 -352
- package/dist/nextjs/routeHandler.js.map +1 -1
- package/dist/react-router-7/components/UserButton.js +1 -1
- package/dist/react-router-7/components/UserButton.js.map +1 -1
- package/dist/react-router-7/routeHandler.d.ts.map +1 -1
- package/dist/react-router-7/routeHandler.js +1 -0
- package/dist/react-router-7/routeHandler.js.map +1 -1
- package/dist/react-router-7/useUser.d.ts.map +1 -1
- package/dist/react-router-7/useUser.js +13 -2
- package/dist/react-router-7/useUser.js.map +1 -1
- package/dist/reactjs/components/ButtonContentOrLoader.d.ts.map +1 -1
- package/dist/reactjs/components/ButtonContentOrLoader.js +2 -4
- package/dist/reactjs/components/ButtonContentOrLoader.js.map +1 -1
- package/dist/reactjs/components/CivicAuthIframeContainer.d.ts +2 -0
- package/dist/reactjs/components/CivicAuthIframeContainer.d.ts.map +1 -0
- package/dist/reactjs/components/CivicAuthIframeContainer.js +26 -0
- package/dist/reactjs/components/CivicAuthIframeContainer.js.map +1 -0
- package/dist/reactjs/components/SignInButton.d.ts.map +1 -1
- package/dist/reactjs/components/SignInButton.js +11 -1
- package/dist/reactjs/components/SignInButton.js.map +1 -1
- package/dist/reactjs/components/UserButton.d.ts +9 -2
- package/dist/reactjs/components/UserButton.d.ts.map +1 -1
- package/dist/reactjs/components/UserButton.js +41 -9
- package/dist/reactjs/components/UserButton.js.map +1 -1
- package/dist/reactjs/components/index.d.ts +1 -0
- package/dist/reactjs/components/index.d.ts.map +1 -1
- package/dist/reactjs/components/index.js +1 -0
- package/dist/reactjs/components/index.js.map +1 -1
- package/dist/reactjs/core/GlobalAuthManager.d.ts +26 -0
- package/dist/reactjs/core/GlobalAuthManager.d.ts.map +1 -1
- package/dist/reactjs/core/GlobalAuthManager.js +76 -5
- package/dist/reactjs/core/GlobalAuthManager.js.map +1 -1
- package/dist/reactjs/hooks/useUser.d.ts +19 -2
- package/dist/reactjs/hooks/useUser.d.ts.map +1 -1
- package/dist/reactjs/hooks/useUser.js +95 -7
- package/dist/reactjs/hooks/useUser.js.map +1 -1
- package/dist/reactjs/index.d.ts +1 -2
- package/dist/reactjs/index.d.ts.map +1 -1
- package/dist/reactjs/index.js +1 -2
- package/dist/reactjs/index.js.map +1 -1
- package/dist/reactjs/providers/CivicAuthProvider.d.ts +2 -1
- package/dist/reactjs/providers/CivicAuthProvider.d.ts.map +1 -1
- package/dist/reactjs/providers/CivicAuthProvider.js +3 -1
- package/dist/reactjs/providers/CivicAuthProvider.js.map +1 -1
- package/dist/server/ServerAuthenticationResolver.d.ts.map +1 -1
- package/dist/server/ServerAuthenticationResolver.js +18 -0
- package/dist/server/ServerAuthenticationResolver.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/session.d.ts +51 -0
- package/dist/server/session.d.ts.map +1 -1
- package/dist/server/session.js +276 -15
- package/dist/server/session.js.map +1 -1
- package/dist/shared/components/SVGLoading.js +1 -1
- package/dist/shared/components/SVGLoading.js.map +1 -1
- package/dist/shared/components/UserButtonPresentation.d.ts.map +1 -0
- package/dist/shared/components/UserButtonPresentation.js.map +1 -0
- package/dist/shared/hooks/index.d.ts +1 -2
- package/dist/shared/hooks/index.d.ts.map +1 -1
- package/dist/shared/hooks/index.js +1 -2
- package/dist/shared/hooks/index.js.map +1 -1
- package/dist/shared/hooks/useBfcacheHandler.d.ts +23 -0
- package/dist/shared/hooks/useBfcacheHandler.d.ts.map +1 -0
- package/dist/shared/hooks/useBfcacheHandler.js +65 -0
- package/dist/shared/hooks/useBfcacheHandler.js.map +1 -0
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +1 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/lib/util.d.ts +32 -0
- package/dist/shared/lib/util.d.ts.map +1 -1
- package/dist/shared/lib/util.js +79 -0
- package/dist/shared/lib/util.js.map +1 -1
- package/dist/shared/providers/AuthStatusContext.d.ts.map +1 -1
- package/dist/shared/providers/AuthStatusContext.js +2 -1
- package/dist/shared/providers/AuthStatusContext.js.map +1 -1
- package/dist/shared/providers/CivicAuthConfigContext.d.ts +2 -1
- package/dist/shared/providers/CivicAuthConfigContext.d.ts.map +1 -1
- package/dist/shared/providers/CivicAuthConfigContext.js +5 -2
- package/dist/shared/providers/CivicAuthConfigContext.js.map +1 -1
- package/dist/shared/providers/types.d.ts +1 -0
- package/dist/shared/providers/types.d.ts.map +1 -1
- package/dist/shared/providers/types.js.map +1 -1
- package/dist/shared/utils/locationChange.d.ts +34 -0
- package/dist/shared/utils/locationChange.d.ts.map +1 -0
- package/dist/shared/utils/locationChange.js +28 -0
- package/dist/shared/utils/locationChange.js.map +1 -0
- package/dist/shared/version.d.ts +1 -1
- package/dist/shared/version.d.ts.map +1 -1
- package/dist/shared/version.js +1 -1
- package/dist/shared/version.js.map +1 -1
- package/dist/vanillajs/auth/AuthenticationEvents.d.ts +10 -1
- package/dist/vanillajs/auth/AuthenticationEvents.d.ts.map +1 -1
- package/dist/vanillajs/auth/AuthenticationEvents.js +29 -0
- package/dist/vanillajs/auth/AuthenticationEvents.js.map +1 -1
- package/dist/vanillajs/auth/BackendAuthenticationRefresher.d.ts.map +1 -1
- package/dist/vanillajs/auth/BackendAuthenticationRefresher.js +2 -2
- package/dist/vanillajs/auth/BackendAuthenticationRefresher.js.map +1 -1
- package/dist/vanillajs/auth/CivicAuth.d.ts +32 -0
- package/dist/vanillajs/auth/CivicAuth.d.ts.map +1 -1
- package/dist/vanillajs/auth/CivicAuth.js +255 -55
- package/dist/vanillajs/auth/CivicAuth.js.map +1 -1
- package/dist/vanillajs/auth/SessionManager.d.ts +3 -2
- package/dist/vanillajs/auth/SessionManager.d.ts.map +1 -1
- package/dist/vanillajs/auth/SessionManager.js +33 -7
- package/dist/vanillajs/auth/SessionManager.js.map +1 -1
- package/dist/vanillajs/auth/config/ConfigProcessor.d.ts.map +1 -1
- package/dist/vanillajs/auth/config/ConfigProcessor.js +2 -14
- package/dist/vanillajs/auth/config/ConfigProcessor.js.map +1 -1
- package/dist/vanillajs/auth/handlers/IframeAuthHandler.d.ts.map +1 -1
- package/dist/vanillajs/auth/handlers/IframeAuthHandler.js +64 -11
- package/dist/vanillajs/auth/handlers/IframeAuthHandler.js.map +1 -1
- package/dist/vanillajs/auth/handlers/MessageHandler.d.ts.map +1 -1
- package/dist/vanillajs/auth/handlers/MessageHandler.js +4 -1
- package/dist/vanillajs/auth/handlers/MessageHandler.js.map +1 -1
- package/dist/vanillajs/auth/handlers/PopupHandler.d.ts.map +1 -1
- package/dist/vanillajs/auth/handlers/PopupHandler.js +3 -1
- package/dist/vanillajs/auth/handlers/PopupHandler.js.map +1 -1
- package/dist/vanillajs/auth/types/AuthTypes.d.ts +11 -1
- package/dist/vanillajs/auth/types/AuthTypes.d.ts.map +1 -1
- package/dist/vanillajs/auth/types/AuthTypes.js.map +1 -1
- package/dist/vanillajs/iframe/IframeManager.d.ts +22 -1
- package/dist/vanillajs/iframe/IframeManager.d.ts.map +1 -1
- package/dist/vanillajs/iframe/IframeManager.js +184 -22
- package/dist/vanillajs/iframe/IframeManager.js.map +1 -1
- package/dist/vanillajs/types/index.d.ts +1 -1
- package/dist/vanillajs/types/index.d.ts.map +1 -1
- package/dist/vanillajs/types/index.js +1 -1
- package/dist/vanillajs/types/index.js.map +1 -1
- package/dist/vanillajs/ui/LoadingComponents.d.ts +4 -0
- package/dist/vanillajs/ui/LoadingComponents.d.ts.map +1 -1
- package/dist/vanillajs/ui/LoadingComponents.js +51 -1
- package/dist/vanillajs/ui/LoadingComponents.js.map +1 -1
- package/package.json +3 -3
- package/dist/nextjs/hooks/index.d.ts +0 -2
- package/dist/nextjs/hooks/index.d.ts.map +0 -1
- package/dist/nextjs/hooks/index.js +0 -2
- package/dist/nextjs/hooks/index.js.map +0 -1
- package/dist/nextjs/hooks/usePrevious.d.ts +0 -2
- package/dist/nextjs/hooks/usePrevious.d.ts.map +0 -1
- package/dist/nextjs/hooks/usePrevious.js +0 -9
- package/dist/nextjs/hooks/usePrevious.js.map +0 -1
- package/dist/nextjs/hooks/useUserCookie.d.ts +0 -9
- package/dist/nextjs/hooks/useUserCookie.d.ts.map +0 -1
- package/dist/nextjs/hooks/useUserCookie.js +0 -109
- package/dist/nextjs/hooks/useUserCookie.js.map +0 -1
- package/dist/react-router-7/components/UserButtonPresentation.d.ts.map +0 -1
- package/dist/react-router-7/components/UserButtonPresentation.js.map +0 -1
- package/dist/shared/components/BlockDisplay.d.ts +0 -6
- package/dist/shared/components/BlockDisplay.d.ts.map +0 -1
- package/dist/shared/components/BlockDisplay.js +0 -30
- package/dist/shared/components/BlockDisplay.js.map +0 -1
- package/dist/shared/components/CivicAuthIframe.d.ts +0 -10
- package/dist/shared/components/CivicAuthIframe.d.ts.map +0 -1
- package/dist/shared/components/CivicAuthIframe.js +0 -49
- package/dist/shared/components/CivicAuthIframe.js.map +0 -1
- package/dist/shared/components/CivicAuthIframeContainer.d.ts +0 -15
- package/dist/shared/components/CivicAuthIframeContainer.d.ts.map +0 -1
- package/dist/shared/components/CivicAuthIframeContainer.js +0 -177
- package/dist/shared/components/CivicAuthIframeContainer.js.map +0 -1
- package/dist/shared/components/CivicAuthLogoutIframeContainer.d.ts +0 -6
- package/dist/shared/components/CivicAuthLogoutIframeContainer.d.ts.map +0 -1
- package/dist/shared/components/CivicAuthLogoutIframeContainer.js +0 -51
- package/dist/shared/components/CivicAuthLogoutIframeContainer.js.map +0 -1
- package/dist/shared/components/IFrameAndLoading.d.ts +0 -7
- package/dist/shared/components/IFrameAndLoading.d.ts.map +0 -1
- package/dist/shared/components/IFrameAndLoading.js +0 -66
- package/dist/shared/components/IFrameAndLoading.js.map +0 -1
- package/dist/shared/hooks/useAuth.d.ts +0 -3
- package/dist/shared/hooks/useAuth.d.ts.map +0 -1
- package/dist/shared/hooks/useAuth.js +0 -12
- package/dist/shared/hooks/useAuth.js.map +0 -1
- package/dist/shared/hooks/useIframe.d.ts +0 -3
- package/dist/shared/hooks/useIframe.d.ts.map +0 -1
- package/dist/shared/hooks/useIframe.js +0 -13
- package/dist/shared/hooks/useIframe.js.map +0 -1
- package/dist/shared/hooks/useIsInIframe.d.ts +0 -7
- package/dist/shared/hooks/useIsInIframe.d.ts.map +0 -1
- package/dist/shared/hooks/useIsInIframe.js +0 -23
- package/dist/shared/hooks/useIsInIframe.js.map +0 -1
- package/dist/shared/hooks/useSignIn.d.ts +0 -20
- package/dist/shared/hooks/useSignIn.d.ts.map +0 -1
- package/dist/shared/hooks/useSignIn.js +0 -358
- package/dist/shared/hooks/useSignIn.js.map +0 -1
- package/dist/shared/providers/IframeProvider.d.ts +0 -28
- package/dist/shared/providers/IframeProvider.d.ts.map +0 -1
- package/dist/shared/providers/IframeProvider.js +0 -64
- package/dist/shared/providers/IframeProvider.js.map +0 -1
- /package/dist/{react-router-7 โ shared}/components/UserButtonPresentation.d.ts +0 -0
- /package/dist/{react-router-7 โ shared}/components/UserButtonPresentation.js +0 -0
|
@@ -8,7 +8,7 @@ import { AuthenticationEvents } from "./AuthenticationEvents.js";
|
|
|
8
8
|
import { PopupError } from "../../services/types.js";
|
|
9
9
|
import { getVersion } from "../../shared/index.js";
|
|
10
10
|
import { handleOAuthRedirectPage } from "./handlers/OAuthCallbackHandler.js";
|
|
11
|
-
import { generateOauthLogoutUrl, clearTokens, retrieveTokens, getBackendEndpoints, } from "../../shared/lib/util.js";
|
|
11
|
+
import { generateOauthLogoutUrl, clearTokens, retrieveTokens, getBackendEndpoints, resolveEndpointUrl, } from "../../shared/lib/util.js";
|
|
12
12
|
import { LOGOUT_STATE } from "../../constants.js";
|
|
13
13
|
import { getOauthEndpoints } from "../../lib/oauth.js";
|
|
14
14
|
import { collectAndSendSDKAnalytics } from "../../lib/analytics.js";
|
|
@@ -74,7 +74,7 @@ export class CivicAuth {
|
|
|
74
74
|
// Always initialize events - use provided events or create default instance
|
|
75
75
|
this.events = config.events || new AuthenticationEvents();
|
|
76
76
|
// Always initialize SessionManager
|
|
77
|
-
this.sessionManager = new SessionManager(this.storage, this.events, this.config);
|
|
77
|
+
this.sessionManager = new SessionManager(this.storage, this.events, this.config, this.config.initialUser);
|
|
78
78
|
// Initialize handlers
|
|
79
79
|
this.initializeHandlers();
|
|
80
80
|
}
|
|
@@ -172,13 +172,33 @@ export class CivicAuth {
|
|
|
172
172
|
else {
|
|
173
173
|
this.logger.info("๐ Not a callback page, initialization complete");
|
|
174
174
|
}
|
|
175
|
-
//
|
|
176
|
-
//
|
|
177
|
-
this.
|
|
178
|
-
|
|
175
|
+
// Check if we're in embedded mode - we need to show the iframe
|
|
176
|
+
// Note: After config processing, "embedded" displayMode becomes "iframe" + iframeDisplayMode: "embedded"
|
|
177
|
+
const isEmbeddedMode = this.config.displayMode === "iframe" &&
|
|
178
|
+
this.config.iframeDisplayMode === "embedded";
|
|
179
|
+
this.logger.info("๐ Checking display mode conditions", {
|
|
179
180
|
displayMode: this.config.displayMode,
|
|
181
|
+
iframeDisplayMode: this.config.iframeDisplayMode,
|
|
182
|
+
isEmbeddedMode,
|
|
183
|
+
preloadIframe: this.config.preloadIframe,
|
|
180
184
|
});
|
|
181
|
-
if (
|
|
185
|
+
if (isEmbeddedMode) {
|
|
186
|
+
// For embedded mode, we need to start authentication to show the iframe
|
|
187
|
+
try {
|
|
188
|
+
this.logger.info("๐ผ๏ธ Starting authentication for embedded mode to show iframe...");
|
|
189
|
+
await this.startAuthentication();
|
|
190
|
+
this.logger.info("โ
Embedded iframe authentication started successfully");
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
// Don't fail initialization if embedded authentication fails - graceful degradation
|
|
194
|
+
this.logger.warn("โ ๏ธ Embedded authentication failed (graceful degradation):", {
|
|
195
|
+
error: error instanceof Error ? error.message : String(error),
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
else if (this.config.preloadIframe &&
|
|
200
|
+
this.config.displayMode === "iframe") {
|
|
201
|
+
// Regular iframe preloading logic for modal mode
|
|
182
202
|
try {
|
|
183
203
|
const isAuthenticated = await this.isAuthenticated();
|
|
184
204
|
this.logger.info("๐ Authentication check for preload", {
|
|
@@ -204,9 +224,12 @@ export class CivicAuth {
|
|
|
204
224
|
this.logger.info("โน๏ธ Auto-preload conditions not met", {
|
|
205
225
|
preloadIframe: this.config.preloadIframe,
|
|
206
226
|
displayMode: this.config.displayMode,
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
227
|
+
isEmbeddedMode,
|
|
228
|
+
reason: isEmbeddedMode
|
|
229
|
+
? "embedded mode uses startAuthentication instead"
|
|
230
|
+
: !this.config.preloadIframe
|
|
231
|
+
? "preloadIframe is disabled"
|
|
232
|
+
: "displayMode is not iframe",
|
|
210
233
|
});
|
|
211
234
|
}
|
|
212
235
|
}
|
|
@@ -298,6 +321,7 @@ export class CivicAuth {
|
|
|
298
321
|
iframeDisplayMode: this.config.iframeDisplayMode,
|
|
299
322
|
framework: this.config.framework || "vanillajs",
|
|
300
323
|
sdkVersion: getVersion(),
|
|
324
|
+
loginSuccessUrl: this.config.loginSuccessUrl,
|
|
301
325
|
});
|
|
302
326
|
// Append state as query parameter to loginUrl
|
|
303
327
|
const url = new URL(this.loginUrl, window.location.origin);
|
|
@@ -324,6 +348,7 @@ export class CivicAuth {
|
|
|
324
348
|
iframeDisplayMode: this.config.iframeDisplayMode,
|
|
325
349
|
framework: this.config.framework || "vanillajs",
|
|
326
350
|
sdkVersion: getVersion(),
|
|
351
|
+
loginSuccessUrl: this.config.loginSuccessUrl,
|
|
327
352
|
});
|
|
328
353
|
return buildAuthUrl({
|
|
329
354
|
endpoints: this.endpoints,
|
|
@@ -474,6 +499,82 @@ export class CivicAuth {
|
|
|
474
499
|
});
|
|
475
500
|
return this.authPromise;
|
|
476
501
|
}
|
|
502
|
+
/**
|
|
503
|
+
* Reloads embedded authentication interface
|
|
504
|
+
*
|
|
505
|
+
* This method is specifically designed for embedded mode scenarios where the iframe
|
|
506
|
+
* needs to be recreated after navigation or DOM changes. It performs a complete
|
|
507
|
+
* re-initialization by calling the full init() method.
|
|
508
|
+
*
|
|
509
|
+
* @returns Promise that resolves when the embedded iframe is created
|
|
510
|
+
* @throws {CivicAuthError} If not in embedded mode or if iframe creation fails
|
|
511
|
+
*
|
|
512
|
+
* @example
|
|
513
|
+
* ```typescript
|
|
514
|
+
* // After navigation in a SPA
|
|
515
|
+
* await civicAuth.reloadEmbedded();
|
|
516
|
+
* ```
|
|
517
|
+
*/
|
|
518
|
+
async reloadEmbedded() {
|
|
519
|
+
this.logger.info("๐ Reloading embedded authentication interface", {
|
|
520
|
+
displayMode: this.config.displayMode,
|
|
521
|
+
iframeDisplayMode: this.config.iframeDisplayMode,
|
|
522
|
+
authPromise: !!this.authPromise,
|
|
523
|
+
});
|
|
524
|
+
this.config.displayMode = "iframe";
|
|
525
|
+
this.config.iframeDisplayMode = "embedded";
|
|
526
|
+
// Check if container element exists
|
|
527
|
+
const container = this.getContainerElement();
|
|
528
|
+
this.logger.info("๐ฏ Container element check", {
|
|
529
|
+
containerFound: !!container,
|
|
530
|
+
containerId: container?.id,
|
|
531
|
+
containerClass: container?.className,
|
|
532
|
+
});
|
|
533
|
+
if (!container) {
|
|
534
|
+
const error = new CivicAuthError("Container element for embedded iframe not found. Ensure an element with id 'civic-login-container' exists or provide targetContainerElement in config.", CivicAuthErrorCode.CONTAINER_NOT_FOUND);
|
|
535
|
+
this.logger.error(error.message);
|
|
536
|
+
throw error;
|
|
537
|
+
}
|
|
538
|
+
// Clear any existing auth promise to ensure fresh start
|
|
539
|
+
if (this.authPromise) {
|
|
540
|
+
this.logger.info("๐งน Clearing existing auth promise for fresh start");
|
|
541
|
+
this.authPromise = undefined;
|
|
542
|
+
this.authPromiseResolve = undefined;
|
|
543
|
+
this.authPromiseReject = undefined;
|
|
544
|
+
}
|
|
545
|
+
// Clean up any existing handlers before re-initialization
|
|
546
|
+
if (this.messageHandler || this.popupHandler || this.iframeAuthHandler) {
|
|
547
|
+
this.logger.info("๐งน Cleaning up existing handlers before re-initialization");
|
|
548
|
+
this.cleanup();
|
|
549
|
+
}
|
|
550
|
+
this.logger.info("๐ Re-initializing handlers and starting embedded auth");
|
|
551
|
+
try {
|
|
552
|
+
// Don't call init() - that would re-process config based on current page
|
|
553
|
+
// Instead, do minimal re-initialization with original config
|
|
554
|
+
// Ensure OAuth endpoints are available (they should be from original init)
|
|
555
|
+
if (!this.endpoints) {
|
|
556
|
+
this.logger.info("๐ Getting OAuth endpoints");
|
|
557
|
+
this.endpoints = await getOauthEndpoints(this.config.oauthServerBaseUrl);
|
|
558
|
+
}
|
|
559
|
+
// Re-initialize all handlers (creates new instances)
|
|
560
|
+
this.logger.info("๐ Re-initializing handlers");
|
|
561
|
+
this.initializeHandlers();
|
|
562
|
+
// Start authentication to create the embedded iframe
|
|
563
|
+
this.logger.info("๐ฌ Starting embedded authentication");
|
|
564
|
+
await this.startAuthentication();
|
|
565
|
+
this.logger.info("โ
Embedded iframe reloaded successfully");
|
|
566
|
+
}
|
|
567
|
+
catch (error) {
|
|
568
|
+
const errorMessage = error instanceof Error
|
|
569
|
+
? error.message
|
|
570
|
+
: "Failed to reload embedded iframe";
|
|
571
|
+
this.logger.error("โ Failed to reload embedded iframe", {
|
|
572
|
+
error: errorMessage,
|
|
573
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
574
|
+
});
|
|
575
|
+
throw error;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
477
578
|
async handleBrowserCorsFailsSilently() {
|
|
478
579
|
this.logger.warn("๐จ Browser CORS fails silently - switching to redirect mode", {
|
|
479
580
|
displayMode: this.config.displayMode,
|
|
@@ -510,7 +611,7 @@ export class CivicAuth {
|
|
|
510
611
|
switch (this.config.displayMode) {
|
|
511
612
|
case "redirect":
|
|
512
613
|
this.logger.info("๐ Using redirect mode");
|
|
513
|
-
|
|
614
|
+
this.events.locationChange(fullAuthUrl, "Redirecting to auth URL", "login");
|
|
514
615
|
break;
|
|
515
616
|
case "new_tab":
|
|
516
617
|
this.logger.info("๐ฑ Using new_tab mode");
|
|
@@ -614,7 +715,19 @@ export class CivicAuth {
|
|
|
614
715
|
handleAuthSuccess(result) {
|
|
615
716
|
this.logger.info("โ
Authentication successful");
|
|
616
717
|
this.authPromiseResolve?.(result);
|
|
617
|
-
|
|
718
|
+
// For embedded mode, preserve the iframe completely - don't cleanup
|
|
719
|
+
// The iframe should stay visible showing the successful authentication state
|
|
720
|
+
const isEmbeddedMode = this.config.displayMode === "iframe" &&
|
|
721
|
+
this.config.iframeDisplayMode === "embedded";
|
|
722
|
+
if (isEmbeddedMode) {
|
|
723
|
+
this.logger.info("๐ง Embedded mode - preserving iframe, skipping cleanup");
|
|
724
|
+
// Only clean up timeouts and reset promises, but keep iframe visible
|
|
725
|
+
this.cleanupTimeoutsAndState();
|
|
726
|
+
}
|
|
727
|
+
else {
|
|
728
|
+
// For modal/redirect modes, do full cleanup as before
|
|
729
|
+
this.cleanup();
|
|
730
|
+
}
|
|
618
731
|
}
|
|
619
732
|
/**
|
|
620
733
|
* Handle authentication error
|
|
@@ -622,7 +735,19 @@ export class CivicAuth {
|
|
|
622
735
|
handleAuthError(error) {
|
|
623
736
|
this.logger.error("โ Authentication failed", { error: error.message });
|
|
624
737
|
this.authPromiseReject?.(error);
|
|
625
|
-
|
|
738
|
+
// For embedded mode, preserve the iframe to show error state
|
|
739
|
+
// For other modes, do full cleanup as before
|
|
740
|
+
const isEmbeddedMode = this.config.displayMode === "iframe" &&
|
|
741
|
+
this.config.iframeDisplayMode === "embedded";
|
|
742
|
+
if (isEmbeddedMode) {
|
|
743
|
+
this.logger.info("๐ง Embedded mode - preserving iframe to show error state");
|
|
744
|
+
// Only clean up timeouts and reset promises, but keep iframe visible
|
|
745
|
+
this.cleanupTimeoutsAndState();
|
|
746
|
+
}
|
|
747
|
+
else {
|
|
748
|
+
// For modal/redirect modes, do full cleanup as before
|
|
749
|
+
this.cleanup();
|
|
750
|
+
}
|
|
626
751
|
}
|
|
627
752
|
/**
|
|
628
753
|
* Handle popup failure - simplified like React implementation
|
|
@@ -638,21 +763,22 @@ export class CivicAuth {
|
|
|
638
763
|
}
|
|
639
764
|
// Always redirect to the failed URL or build a new one
|
|
640
765
|
if (failedUrl) {
|
|
641
|
-
|
|
766
|
+
// this.config.displayMode = "redirect";
|
|
767
|
+
// Use centralized location change handler
|
|
768
|
+
this.events.locationChange(failedUrl, "Popup blocked, falling back to redirect mode", "login");
|
|
769
|
+
return;
|
|
642
770
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
error,
|
|
651
|
-
});
|
|
652
|
-
const fallbackError = new CivicAuthError("Failed to redirect for authentication", CivicAuthErrorCode.INIT_FAILED);
|
|
653
|
-
this.handleAuthError(fallbackError);
|
|
771
|
+
this.buildAuthUrl()
|
|
772
|
+
.then((authUrl) => {
|
|
773
|
+
this.events.locationChange(authUrl, "Redirecting to auth URL", "login");
|
|
774
|
+
})
|
|
775
|
+
.catch((error) => {
|
|
776
|
+
this.logger.error("Failed to build auth URL for redirect fallback", {
|
|
777
|
+
error,
|
|
654
778
|
});
|
|
655
|
-
|
|
779
|
+
const fallbackError = new CivicAuthError("Failed to redirect for authentication", CivicAuthErrorCode.INIT_FAILED);
|
|
780
|
+
this.handleAuthError(fallbackError);
|
|
781
|
+
});
|
|
656
782
|
}
|
|
657
783
|
/**
|
|
658
784
|
* Show popup failure message to user
|
|
@@ -716,7 +842,16 @@ export class CivicAuth {
|
|
|
716
842
|
}
|
|
717
843
|
return element;
|
|
718
844
|
}
|
|
719
|
-
|
|
845
|
+
if (this.config.targetContainerElement) {
|
|
846
|
+
return this.config.targetContainerElement;
|
|
847
|
+
}
|
|
848
|
+
// Fallback: Look for element with id "civic-login-container"
|
|
849
|
+
const fallbackContainer = document.getElementById("civic-login-container");
|
|
850
|
+
if (fallbackContainer) {
|
|
851
|
+
this.logger.debug('Using fallback container with id "civic-login-container"');
|
|
852
|
+
return fallbackContainer;
|
|
853
|
+
}
|
|
854
|
+
return null;
|
|
720
855
|
}
|
|
721
856
|
/**
|
|
722
857
|
* Handle OAuth callback
|
|
@@ -810,6 +945,27 @@ export class CivicAuth {
|
|
|
810
945
|
window.removeEventListener("message", this.messageHandler.handleMessage);
|
|
811
946
|
}
|
|
812
947
|
}
|
|
948
|
+
/**
|
|
949
|
+
* Clean up only timeouts and state without touching iframe (for embedded mode)
|
|
950
|
+
*/
|
|
951
|
+
cleanupTimeoutsAndState() {
|
|
952
|
+
this.logger.info("Cleaning up timeouts and state (preserving iframe for embedded mode)");
|
|
953
|
+
// Clean up timeouts
|
|
954
|
+
if (this.authProcessTimeoutHandle) {
|
|
955
|
+
window.clearTimeout(this.authProcessTimeoutHandle);
|
|
956
|
+
this.authProcessTimeoutHandle = undefined;
|
|
957
|
+
}
|
|
958
|
+
if (this.popupFailureTimeoutHandle) {
|
|
959
|
+
window.clearTimeout(this.popupFailureTimeoutHandle);
|
|
960
|
+
this.popupFailureTimeoutHandle = undefined;
|
|
961
|
+
}
|
|
962
|
+
// Reset state
|
|
963
|
+
this.hasPopupFailed = false;
|
|
964
|
+
this.authPromise = undefined;
|
|
965
|
+
this.authPromiseResolve = undefined;
|
|
966
|
+
this.authPromiseReject = undefined;
|
|
967
|
+
// Keep message handler and iframe for embedded mode
|
|
968
|
+
}
|
|
813
969
|
/**
|
|
814
970
|
* Get the current session
|
|
815
971
|
*/
|
|
@@ -917,6 +1073,37 @@ export class CivicAuth {
|
|
|
917
1073
|
getIframeDisplayMode() {
|
|
918
1074
|
return this.config.iframeDisplayMode;
|
|
919
1075
|
}
|
|
1076
|
+
/**
|
|
1077
|
+
* Reset authentication state when page is restored from back-forward cache (bfcache)
|
|
1078
|
+
* This clears any pending authentication promises that may have been interrupted
|
|
1079
|
+
* by the browser caching the page, allowing fresh authentication attempts
|
|
1080
|
+
*/
|
|
1081
|
+
resetOnBfcache() {
|
|
1082
|
+
this.logger.info("๐ Resetting authentication state due to bfcache restore");
|
|
1083
|
+
// Clear pending authentication promise and related state
|
|
1084
|
+
if (this.authPromise) {
|
|
1085
|
+
this.logger.debug("Clearing stale authentication promise from bfcache");
|
|
1086
|
+
this.authPromise = undefined;
|
|
1087
|
+
this.authPromiseResolve = undefined;
|
|
1088
|
+
this.authPromiseReject = undefined;
|
|
1089
|
+
}
|
|
1090
|
+
// Clear timeouts that may no longer be valid
|
|
1091
|
+
if (this.authProcessTimeoutHandle) {
|
|
1092
|
+
window.clearTimeout(this.authProcessTimeoutHandle);
|
|
1093
|
+
this.authProcessTimeoutHandle = undefined;
|
|
1094
|
+
}
|
|
1095
|
+
if (this.popupFailureTimeoutHandle) {
|
|
1096
|
+
window.clearTimeout(this.popupFailureTimeoutHandle);
|
|
1097
|
+
this.popupFailureTimeoutHandle = undefined;
|
|
1098
|
+
}
|
|
1099
|
+
// Reset auth flags
|
|
1100
|
+
this.hasPopupFailed = false;
|
|
1101
|
+
this.hasSignInStarted = false;
|
|
1102
|
+
// Reset iframe handler state if needed
|
|
1103
|
+
if (this.iframeAuthHandler) {
|
|
1104
|
+
this.iframeAuthHandler.cleanupIframe();
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
920
1107
|
/**
|
|
921
1108
|
* Destroy the auth client and clean up all resources
|
|
922
1109
|
*/
|
|
@@ -940,17 +1127,23 @@ export class CivicAuth {
|
|
|
940
1127
|
this.logger.info("๐ช Redirecting to backend for logout in backend-integrated flow");
|
|
941
1128
|
const backendUrl = new URL(this.loginUrl).origin;
|
|
942
1129
|
const endpoints = getBackendEndpoints(this.config.backendEndpoints);
|
|
943
|
-
const backendLogoutUrl =
|
|
1130
|
+
const backendLogoutUrl = resolveEndpointUrl(backendUrl, endpoints.logout);
|
|
944
1131
|
// Clear local SDK session state before redirecting
|
|
945
1132
|
await this.sessionManager.clearSession();
|
|
946
1133
|
this.events.emit(AuthEvent.SIGN_OUT_COMPLETE, {
|
|
947
1134
|
detail: "Local session cleared, redirecting to backend for logout.",
|
|
948
1135
|
});
|
|
949
1136
|
// Perform top-level redirect to the backend logout endpoint
|
|
950
|
-
|
|
951
|
-
|
|
1137
|
+
// Include logoutRedirectUrl as a query parameter if configured
|
|
1138
|
+
const logoutUrl = new URL(backendLogoutUrl);
|
|
1139
|
+
if (this.config.logoutRedirectUrl) {
|
|
1140
|
+
logoutUrl.searchParams.set("logoutRedirectUrl", this.config.logoutRedirectUrl);
|
|
1141
|
+
}
|
|
1142
|
+
this.logger.info("๐ Loading backend logout endpoint in iframe", {
|
|
1143
|
+
url: logoutUrl.toString(),
|
|
1144
|
+
logoutRedirectUrl: this.config.logoutRedirectUrl,
|
|
952
1145
|
});
|
|
953
|
-
window.location.href =
|
|
1146
|
+
window.location.href = logoutUrl.toString();
|
|
954
1147
|
return;
|
|
955
1148
|
}
|
|
956
1149
|
// --- Existing SPA redirect-based logout flow ---
|
|
@@ -1002,30 +1195,7 @@ export class CivicAuth {
|
|
|
1002
1195
|
detail: "Logout successful",
|
|
1003
1196
|
});
|
|
1004
1197
|
// Use hidden iframe instead of redirect to avoid full page reload in SPA mode
|
|
1005
|
-
this.
|
|
1006
|
-
const logoutIframe = document.createElement("iframe");
|
|
1007
|
-
logoutIframe.style.display = "none";
|
|
1008
|
-
// Clean up iframe when logout completes (or errors)
|
|
1009
|
-
const cleanupIframe = () => {
|
|
1010
|
-
this.logger.info("๐งน Cleaning up logout iframe");
|
|
1011
|
-
if (!logoutIframe.parentNode) {
|
|
1012
|
-
this.logger.warn("๐งน Logout iframe not found, skipping iframe cleanup");
|
|
1013
|
-
return;
|
|
1014
|
-
}
|
|
1015
|
-
logoutIframe.parentNode.removeChild(logoutIframe);
|
|
1016
|
-
if (this.config.logoutRedirectUrl) {
|
|
1017
|
-
window.location.href = this.config.logoutRedirectUrl;
|
|
1018
|
-
}
|
|
1019
|
-
};
|
|
1020
|
-
logoutIframe.onload = () => {
|
|
1021
|
-
cleanupIframe();
|
|
1022
|
-
};
|
|
1023
|
-
logoutIframe.onerror = (error) => {
|
|
1024
|
-
this.logger.error("โ Logout iframe failed to load", { error });
|
|
1025
|
-
cleanupIframe();
|
|
1026
|
-
};
|
|
1027
|
-
logoutIframe.src = logoutUrl.toString();
|
|
1028
|
-
document.body.appendChild(logoutIframe);
|
|
1198
|
+
this.loadLogoutInIframe(logoutUrl);
|
|
1029
1199
|
}
|
|
1030
1200
|
catch (error) {
|
|
1031
1201
|
this.logger.error("โ Logout failed", { error });
|
|
@@ -1035,6 +1205,36 @@ export class CivicAuth {
|
|
|
1035
1205
|
throw new CivicAuthError("Logout failed", CivicAuthErrorCode.LOGOUT_FAILED);
|
|
1036
1206
|
}
|
|
1037
1207
|
}
|
|
1208
|
+
/**
|
|
1209
|
+
* Load logout URL in a hidden iframe to avoid full page reload
|
|
1210
|
+
* @param logoutUrl The URL to load in the iframe
|
|
1211
|
+
*/
|
|
1212
|
+
loadLogoutInIframe(logoutUrl) {
|
|
1213
|
+
this.logger.info("๐ Loading logout URL in hidden iframe");
|
|
1214
|
+
const logoutIframe = document.createElement("iframe");
|
|
1215
|
+
logoutIframe.style.display = "none";
|
|
1216
|
+
// Clean up iframe when logout completes (or errors)
|
|
1217
|
+
const cleanupIframe = () => {
|
|
1218
|
+
this.logger.info("๐งน Cleaning up logout iframe");
|
|
1219
|
+
if (!logoutIframe.parentNode) {
|
|
1220
|
+
this.logger.warn("๐งน Logout iframe not found, skipping iframe cleanup");
|
|
1221
|
+
return;
|
|
1222
|
+
}
|
|
1223
|
+
logoutIframe.parentNode.removeChild(logoutIframe);
|
|
1224
|
+
if (this.config.logoutRedirectUrl) {
|
|
1225
|
+
this.events.locationChange(this.config.logoutRedirectUrl, "Redirecting to logoutRedirectUrl", "logout");
|
|
1226
|
+
}
|
|
1227
|
+
};
|
|
1228
|
+
logoutIframe.onload = () => {
|
|
1229
|
+
cleanupIframe();
|
|
1230
|
+
};
|
|
1231
|
+
logoutIframe.onerror = (error) => {
|
|
1232
|
+
this.logger.error("โ Logout iframe failed to load", { error });
|
|
1233
|
+
cleanupIframe();
|
|
1234
|
+
};
|
|
1235
|
+
logoutIframe.src = logoutUrl.toString();
|
|
1236
|
+
document.body.appendChild(logoutIframe);
|
|
1237
|
+
}
|
|
1038
1238
|
/**
|
|
1039
1239
|
* Handle logout state cleanup
|
|
1040
1240
|
* This mirrors the logic from useSignIn.ts to properly clean up after logout
|