@civic/auth 0.15.2 → 0.15.3
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 +8 -0
- package/dist/nextjs/hooks/useInitialAuthConfig.d.ts.map +1 -1
- package/dist/nextjs/hooks/useInitialAuthConfig.js +57 -53
- package/dist/nextjs/hooks/useInitialAuthConfig.js.map +1 -1
- package/dist/nextjs/providers/NextAuthProviderClient.d.ts.map +1 -1
- package/dist/nextjs/providers/NextAuthProviderClient.js +28 -18
- package/dist/nextjs/providers/NextAuthProviderClient.js.map +1 -1
- package/dist/reactjs/core/GlobalAuthManager.d.ts +13 -1
- package/dist/reactjs/core/GlobalAuthManager.d.ts.map +1 -1
- package/dist/reactjs/core/GlobalAuthManager.js +46 -11
- package/dist/reactjs/core/GlobalAuthManager.js.map +1 -1
- package/dist/shared/version.d.ts +1 -1
- package/dist/shared/version.js +1 -1
- package/dist/shared/version.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
# 0.15.3 - Fix OAuth init loop in Next.js provider
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
- [AUTH-308] Fixed a reference-instability loop in `CivicAuthProvider` that rebuilt the OAuth iframe on every render for users with a valid session, producing repeated `/api/auth/login` redirects. `onUrlChange` / `onSignIn` / `onSignOut` / `onRefresh` are now stable across renders via `useCallback`, and `GlobalAuthManager.initialize` hot-swaps callback references instead of tearing down and recreating the underlying auth instance.
|
|
5
|
+
|
|
6
|
+
### Improvements
|
|
7
|
+
- `GlobalAuthManager.isSameConfig` now compares `iframeMode` structurally so runtime `iframeMode` changes trigger a proper re-init.
|
|
8
|
+
|
|
1
9
|
# 0.15.2 - Fix audit issues
|
|
2
10
|
- Fix various audit findings by updating packages
|
|
3
11
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useInitialAuthConfig.d.ts","sourceRoot":"","sources":["../../../src/nextjs/hooks/useInitialAuthConfig.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EACrB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAKnD,MAAM,WAAW,2BAA2B;IAC1C,WAAW,CAAC,EAAE,oBAAoB,CAAC;IACnC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sBAAsB,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,6BAA6B;IAC5C,WAAW,CAAC,EAAE,oBAAoB,CAAC;IACnC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,aACtB,2BAA2B,KACnC;IACD,aAAa,EAAE,gBAAgB,CAAC;IAChC,yBAAyB,EAAE,CACzB,SAAS,CAAC,EAAE,6BAA6B,KACtC,gBAAgB,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"useInitialAuthConfig.d.ts","sourceRoot":"","sources":["../../../src/nextjs/hooks/useInitialAuthConfig.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EACrB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAKnD,MAAM,WAAW,2BAA2B;IAC1C,WAAW,CAAC,EAAE,oBAAoB,CAAC;IACnC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sBAAsB,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,6BAA6B;IAC5C,WAAW,CAAC,EAAE,oBAAoB,CAAC;IACnC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,aACtB,2BAA2B,KACnC;IACD,aAAa,EAAE,gBAAgB,CAAC;IAChC,yBAAyB,EAAE,CACzB,SAAS,CAAC,EAAE,6BAA6B,KACtC,gBAAgB,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;CAqLvB,CAAC"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Reusable across NextJS components that need to initialize GlobalAuthManager
|
|
4
4
|
*/
|
|
5
5
|
"use client";
|
|
6
|
-
import { useMemo, useState } from "react";
|
|
6
|
+
import { useCallback, useMemo, useState } from "react";
|
|
7
7
|
import { useRouter, usePathname } from "next/navigation.js";
|
|
8
8
|
import { resolveAuthConfig } from "../../nextjs/config.js";
|
|
9
9
|
import { BrowserCookieStorage } from "../../shared/index.js";
|
|
@@ -21,6 +21,56 @@ export const useInitialAuthConfig = (options = {}) => {
|
|
|
21
21
|
// so that client-side hooks and event listeners are properly initialized
|
|
22
22
|
const [hasSignedOut, setHasSignedOut] = useState(false);
|
|
23
23
|
const { clientId, oauthServer, loginSuccessUrl, loginInitUrl, logoutUrl, refreshUrl, userUrl, clearSessionUrl, logoutCallbackUrl, callbackUrl, targetContainerElement, basePath, } = resolvedConfig;
|
|
24
|
+
const onSignOut = useCallback(async () => {
|
|
25
|
+
setHasSignedOut(true);
|
|
26
|
+
await new Promise((resolve) => {
|
|
27
|
+
setTimeout(async () => {
|
|
28
|
+
try {
|
|
29
|
+
// Trigger server-side revalidation to force NextAuthProvider to re-run
|
|
30
|
+
await revalidateUserData(pathname);
|
|
31
|
+
}
|
|
32
|
+
catch (revalidateError) {
|
|
33
|
+
loggers.nextjs.hooks.error("onSignOut: Revalidation failed:", revalidateError);
|
|
34
|
+
// Fallback to router.refresh() if server action fails
|
|
35
|
+
router.refresh();
|
|
36
|
+
}
|
|
37
|
+
resolve(true);
|
|
38
|
+
}, 100);
|
|
39
|
+
});
|
|
40
|
+
}, [pathname, router]);
|
|
41
|
+
const onRefresh = useCallback(async (error) => {
|
|
42
|
+
if (error) {
|
|
43
|
+
loggers.nextjs.hooks.error("onRefresh: Error refreshing", error);
|
|
44
|
+
}
|
|
45
|
+
setHasSignedOut(false);
|
|
46
|
+
await new Promise((resolve) => {
|
|
47
|
+
setTimeout(async () => {
|
|
48
|
+
router.refresh();
|
|
49
|
+
resolve(true);
|
|
50
|
+
}, 100);
|
|
51
|
+
});
|
|
52
|
+
}, [router]);
|
|
53
|
+
const onSignIn = useCallback(async ({ error, redirectUrl }) => {
|
|
54
|
+
if (error) {
|
|
55
|
+
loggers.nextjs.hooks.error("onSignIn: Error signing in", error);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
setHasSignedOut(false);
|
|
59
|
+
try {
|
|
60
|
+
// Trigger server-side revalidation to force NextAuthProvider to re-run
|
|
61
|
+
await revalidateUserData(pathname);
|
|
62
|
+
// Navigate to the deep link (redirectUrl) if available, otherwise fall back to loginSuccessUrl
|
|
63
|
+
const targetUrl = redirectUrl || loginSuccessUrl;
|
|
64
|
+
if (targetUrl && targetUrl !== pathname) {
|
|
65
|
+
router.push(targetUrl);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (revalidateError) {
|
|
69
|
+
loggers.nextjs.hooks.error("onSignIn: Revalidation failed:", revalidateError);
|
|
70
|
+
// Fallback to router.refresh() if server action fails
|
|
71
|
+
router.refresh();
|
|
72
|
+
}
|
|
73
|
+
}, [pathname, loginSuccessUrl, router]);
|
|
24
74
|
const baseConfig = useMemo(() => {
|
|
25
75
|
return {
|
|
26
76
|
disableRefresh: options.disableRefresh,
|
|
@@ -52,56 +102,9 @@ export const useInitialAuthConfig = (options = {}) => {
|
|
|
52
102
|
logout: logoutUrl,
|
|
53
103
|
clearSession: clearSessionUrl,
|
|
54
104
|
},
|
|
55
|
-
onSignOut
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
setTimeout(async () => {
|
|
59
|
-
try {
|
|
60
|
-
// Trigger server-side revalidation to force NextAuthProvider to re-run
|
|
61
|
-
await revalidateUserData(pathname);
|
|
62
|
-
}
|
|
63
|
-
catch (revalidateError) {
|
|
64
|
-
console.error("onSignIn: Revalidation failed:", revalidateError);
|
|
65
|
-
// Fallback to router.refresh() if server action fails
|
|
66
|
-
router.refresh();
|
|
67
|
-
}
|
|
68
|
-
resolve(true);
|
|
69
|
-
}, 100);
|
|
70
|
-
});
|
|
71
|
-
},
|
|
72
|
-
onRefresh: async (error) => {
|
|
73
|
-
if (error) {
|
|
74
|
-
loggers.nextjs.hooks.error("onRefresh: Error refreshing", error);
|
|
75
|
-
}
|
|
76
|
-
setHasSignedOut(false);
|
|
77
|
-
await new Promise((resolve) => {
|
|
78
|
-
setTimeout(async () => {
|
|
79
|
-
router.refresh();
|
|
80
|
-
resolve(true);
|
|
81
|
-
}, 100);
|
|
82
|
-
});
|
|
83
|
-
},
|
|
84
|
-
onSignIn: async ({ error, redirectUrl }) => {
|
|
85
|
-
if (error) {
|
|
86
|
-
loggers.nextjs.hooks.error("onSignIn: Error signing in", error);
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
setHasSignedOut(false);
|
|
90
|
-
try {
|
|
91
|
-
// Trigger server-side revalidation to force NextAuthProvider to re-run
|
|
92
|
-
await revalidateUserData(pathname);
|
|
93
|
-
// Navigate to the deep link (redirectUrl) if available, otherwise fall back to loginSuccessUrl
|
|
94
|
-
const targetUrl = redirectUrl || loginSuccessUrl;
|
|
95
|
-
if (targetUrl && targetUrl !== pathname) {
|
|
96
|
-
router.push(targetUrl);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
catch (revalidateError) {
|
|
100
|
-
console.error("onSignIn: Revalidation failed:", revalidateError);
|
|
101
|
-
// Fallback to router.refresh() if server action fails
|
|
102
|
-
router.refresh();
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
+
onSignOut,
|
|
106
|
+
onRefresh,
|
|
107
|
+
onSignIn,
|
|
105
108
|
onUrlChange: options.onUrlChange,
|
|
106
109
|
initialUser: (!hasSignedOut && options.serverUser) || null,
|
|
107
110
|
initialIdToken: null, // ID token is httpOnly and not accessible
|
|
@@ -126,8 +129,9 @@ export const useInitialAuthConfig = (options = {}) => {
|
|
|
126
129
|
clearSessionUrl,
|
|
127
130
|
basePath,
|
|
128
131
|
hasSignedOut,
|
|
129
|
-
|
|
130
|
-
|
|
132
|
+
onSignOut,
|
|
133
|
+
onRefresh,
|
|
134
|
+
onSignIn,
|
|
131
135
|
]);
|
|
132
136
|
const createConfigWithOverrides = useMemo(() => {
|
|
133
137
|
return (overrides = {}) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useInitialAuthConfig.js","sourceRoot":"","sources":["../../../src/nextjs/hooks/useInitialAuthConfig.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Hook for creating the initial auth configuration\n * Reusable across NextJS components that need to initialize GlobalAuthManager\n */\n\"use client\";\n\nimport { useMemo, useState } from \"react\";\nimport { useRouter, usePathname } from \"next/navigation.js\";\nimport { resolveAuthConfig } from \"@/nextjs/config.js\";\nimport type { GlobalAuthConfig } from \"@/reactjs/core/GlobalAuthManager.js\";\nimport type {\n LoggingConfig,\n VanillaJSDisplayMode,\n} from \"@/vanillajs/auth/types/AuthTypes.js\";\nimport type { User, IframeMode } from \"@/types.js\";\nimport { BrowserCookieStorage } from \"@/shared/index.js\";\nimport { loggers } from \"@/lib/logger.js\";\nimport { revalidateUserData } from \"../actions.js\";\n\nexport interface UseInitialAuthConfigOptions {\n displayMode?: VanillaJSDisplayMode;\n iframeMode?: IframeMode;\n serverUser?: User | null;\n nonce?: string;\n targetContainerElement?: HTMLElement | string;\n oauthServer?: string;\n loginSuccessUrl?: string;\n onUrlChange?: (url: string, source?: string) => void;\n logging?: LoggingConfig;\n disableRefresh?: boolean;\n}\n\nexport interface UseInitialAuthConfigOverrides {\n displayMode?: VanillaJSDisplayMode;\n iframeMode?: IframeMode;\n clientId?: string;\n redirectUrl?: string;\n logoutRedirectUrl?: string;\n targetContainerElement?: string;\n}\n\n/**\n * Hook that creates the initial auth configuration\n * Can be used standalone or merged with overrides\n */\nexport const useInitialAuthConfig = (\n options: UseInitialAuthConfigOptions = {},\n): {\n initialConfig: GlobalAuthConfig;\n createConfigWithOverrides: (\n overrides?: UseInitialAuthConfigOverrides,\n ) => GlobalAuthConfig;\n logoutUrl: string;\n hasSignedOut: boolean;\n} => {\n const router = useRouter();\n const pathname = usePathname();\n const resolvedConfig = resolveAuthConfig(options);\n // Force a re-render when the page gets re-rendered after sign-in/sign-out\n // so that client-side hooks and event listeners are properly initialized\n const [hasSignedOut, setHasSignedOut] = useState<boolean>(false);\n const {\n clientId,\n oauthServer,\n loginSuccessUrl,\n loginInitUrl,\n logoutUrl,\n refreshUrl,\n userUrl,\n clearSessionUrl,\n logoutCallbackUrl,\n callbackUrl,\n targetContainerElement,\n basePath,\n } = resolvedConfig;\n\n const baseConfig: GlobalAuthConfig = useMemo(() => {\n return {\n disableRefresh: options.disableRefresh,\n // we need this to retrieve client-available cookies for auto-refresh etc.\n // Pass basePath to ensure cookies are set/read with the correct path\n storage: new BrowserCookieStorage({ path: basePath || \"/\" }),\n clientId: clientId,\n loginUrl:\n typeof window !== \"undefined\"\n ? window.location.origin + loginInitUrl\n : undefined,\n redirectUrl:\n typeof window !== \"undefined\"\n ? window.location.origin + callbackUrl\n : undefined,\n config: {\n oauthServer: oauthServer,\n oauthServerBaseUrl: oauthServer,\n },\n logoutRedirectUrl: logoutCallbackUrl,\n loginSuccessUrl: loginSuccessUrl,\n targetContainerElement: targetContainerElement,\n displayMode: options.displayMode,\n iframeMode: options.iframeMode,\n logoutCallbackUrl: logoutCallbackUrl,\n framework: \"nextjs\",\n logging: options.logging,\n backendEndpoints: {\n user: userUrl,\n refresh: refreshUrl,\n logout: logoutUrl,\n clearSession: clearSessionUrl,\n },\n onSignOut: async () => {\n setHasSignedOut(true);\n await new Promise((resolve) => {\n setTimeout(async () => {\n try {\n // Trigger server-side revalidation to force NextAuthProvider to re-run\n await revalidateUserData(pathname);\n } catch (revalidateError) {\n console.error(\"onSignIn: Revalidation failed:\", revalidateError);\n // Fallback to router.refresh() if server action fails\n router.refresh();\n }\n resolve(true);\n }, 100);\n });\n },\n onRefresh: async (error) => {\n if (error) {\n loggers.nextjs.hooks.error(\"onRefresh: Error refreshing\", error);\n }\n setHasSignedOut(false);\n\n await new Promise((resolve) => {\n setTimeout(async () => {\n router.refresh();\n resolve(true);\n }, 100);\n });\n },\n onSignIn: async ({ error, redirectUrl }) => {\n if (error) {\n loggers.nextjs.hooks.error(\"onSignIn: Error signing in\", error);\n return;\n }\n setHasSignedOut(false);\n try {\n // Trigger server-side revalidation to force NextAuthProvider to re-run\n await revalidateUserData(pathname);\n // Navigate to the deep link (redirectUrl) if available, otherwise fall back to loginSuccessUrl\n const targetUrl = redirectUrl || loginSuccessUrl;\n if (targetUrl && targetUrl !== pathname) {\n router.push(targetUrl);\n }\n } catch (revalidateError) {\n console.error(\"onSignIn: Revalidation failed:\", revalidateError);\n // Fallback to router.refresh() if server action fails\n router.refresh();\n }\n },\n onUrlChange: options.onUrlChange,\n initialUser: (!hasSignedOut && options.serverUser) || null,\n initialIdToken: null, // ID token is httpOnly and not accessible\n };\n }, [\n options.disableRefresh,\n options.displayMode,\n options.iframeMode,\n options.logging,\n options.onUrlChange,\n options.serverUser,\n clientId,\n loginInitUrl,\n callbackUrl,\n oauthServer,\n logoutCallbackUrl,\n loginSuccessUrl,\n targetContainerElement,\n userUrl,\n refreshUrl,\n logoutUrl,\n clearSessionUrl,\n basePath,\n hasSignedOut,\n pathname,\n router,\n ]);\n\n const createConfigWithOverrides = useMemo(() => {\n return (\n overrides: UseInitialAuthConfigOverrides = {},\n ): GlobalAuthConfig => {\n return {\n ...baseConfig,\n // Override specific properties while keeping the base config\n ...(overrides.displayMode && { displayMode: overrides.displayMode }),\n ...(overrides.iframeMode !== undefined && {\n iframeMode: overrides.iframeMode,\n }),\n ...(overrides.clientId && { clientId: overrides.clientId }),\n ...(overrides.redirectUrl && { redirectUrl: overrides.redirectUrl }),\n ...(overrides.logoutRedirectUrl && {\n logoutRedirectUrl: overrides.logoutRedirectUrl,\n }),\n ...(overrides.targetContainerElement && {\n targetContainerElement: overrides.targetContainerElement,\n }),\n };\n };\n }, [baseConfig]);\n\n return {\n initialConfig: baseConfig,\n createConfigWithOverrides,\n logoutUrl,\n hasSignedOut,\n };\n};\n"]}
|
|
1
|
+
{"version":3,"file":"useInitialAuthConfig.js","sourceRoot":"","sources":["../../../src/nextjs/hooks/useInitialAuthConfig.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Hook for creating the initial auth configuration\n * Reusable across NextJS components that need to initialize GlobalAuthManager\n */\n\"use client\";\n\nimport { useCallback, useMemo, useState } from \"react\";\nimport { useRouter, usePathname } from \"next/navigation.js\";\nimport { resolveAuthConfig } from \"@/nextjs/config.js\";\nimport type { GlobalAuthConfig } from \"@/reactjs/core/GlobalAuthManager.js\";\nimport type {\n LoggingConfig,\n VanillaJSDisplayMode,\n} from \"@/vanillajs/auth/types/AuthTypes.js\";\nimport type { User, IframeMode } from \"@/types.js\";\nimport { BrowserCookieStorage } from \"@/shared/index.js\";\nimport { loggers } from \"@/lib/logger.js\";\nimport { revalidateUserData } from \"../actions.js\";\n\nexport interface UseInitialAuthConfigOptions {\n displayMode?: VanillaJSDisplayMode;\n iframeMode?: IframeMode;\n serverUser?: User | null;\n nonce?: string;\n targetContainerElement?: HTMLElement | string;\n oauthServer?: string;\n loginSuccessUrl?: string;\n onUrlChange?: (url: string, source?: string) => void;\n logging?: LoggingConfig;\n disableRefresh?: boolean;\n}\n\nexport interface UseInitialAuthConfigOverrides {\n displayMode?: VanillaJSDisplayMode;\n iframeMode?: IframeMode;\n clientId?: string;\n redirectUrl?: string;\n logoutRedirectUrl?: string;\n targetContainerElement?: string;\n}\n\n/**\n * Hook that creates the initial auth configuration\n * Can be used standalone or merged with overrides\n */\nexport const useInitialAuthConfig = (\n options: UseInitialAuthConfigOptions = {},\n): {\n initialConfig: GlobalAuthConfig;\n createConfigWithOverrides: (\n overrides?: UseInitialAuthConfigOverrides,\n ) => GlobalAuthConfig;\n logoutUrl: string;\n hasSignedOut: boolean;\n} => {\n const router = useRouter();\n const pathname = usePathname();\n const resolvedConfig = resolveAuthConfig(options);\n // Force a re-render when the page gets re-rendered after sign-in/sign-out\n // so that client-side hooks and event listeners are properly initialized\n const [hasSignedOut, setHasSignedOut] = useState<boolean>(false);\n const {\n clientId,\n oauthServer,\n loginSuccessUrl,\n loginInitUrl,\n logoutUrl,\n refreshUrl,\n userUrl,\n clearSessionUrl,\n logoutCallbackUrl,\n callbackUrl,\n targetContainerElement,\n basePath,\n } = resolvedConfig;\n\n const onSignOut = useCallback(async () => {\n setHasSignedOut(true);\n await new Promise((resolve) => {\n setTimeout(async () => {\n try {\n // Trigger server-side revalidation to force NextAuthProvider to re-run\n await revalidateUserData(pathname);\n } catch (revalidateError) {\n loggers.nextjs.hooks.error(\n \"onSignOut: Revalidation failed:\",\n revalidateError,\n );\n // Fallback to router.refresh() if server action fails\n router.refresh();\n }\n resolve(true);\n }, 100);\n });\n }, [pathname, router]);\n\n const onRefresh = useCallback(\n async (error?: Error) => {\n if (error) {\n loggers.nextjs.hooks.error(\"onRefresh: Error refreshing\", error);\n }\n setHasSignedOut(false);\n\n await new Promise((resolve) => {\n setTimeout(async () => {\n router.refresh();\n resolve(true);\n }, 100);\n });\n },\n [router],\n );\n\n const onSignIn = useCallback(\n async ({ error, redirectUrl }: { error?: Error; redirectUrl?: string }) => {\n if (error) {\n loggers.nextjs.hooks.error(\"onSignIn: Error signing in\", error);\n return;\n }\n setHasSignedOut(false);\n try {\n // Trigger server-side revalidation to force NextAuthProvider to re-run\n await revalidateUserData(pathname);\n // Navigate to the deep link (redirectUrl) if available, otherwise fall back to loginSuccessUrl\n const targetUrl = redirectUrl || loginSuccessUrl;\n if (targetUrl && targetUrl !== pathname) {\n router.push(targetUrl);\n }\n } catch (revalidateError) {\n loggers.nextjs.hooks.error(\n \"onSignIn: Revalidation failed:\",\n revalidateError,\n );\n // Fallback to router.refresh() if server action fails\n router.refresh();\n }\n },\n [pathname, loginSuccessUrl, router],\n );\n\n const baseConfig: GlobalAuthConfig = useMemo(() => {\n return {\n disableRefresh: options.disableRefresh,\n // we need this to retrieve client-available cookies for auto-refresh etc.\n // Pass basePath to ensure cookies are set/read with the correct path\n storage: new BrowserCookieStorage({ path: basePath || \"/\" }),\n clientId: clientId,\n loginUrl:\n typeof window !== \"undefined\"\n ? window.location.origin + loginInitUrl\n : undefined,\n redirectUrl:\n typeof window !== \"undefined\"\n ? window.location.origin + callbackUrl\n : undefined,\n config: {\n oauthServer: oauthServer,\n oauthServerBaseUrl: oauthServer,\n },\n logoutRedirectUrl: logoutCallbackUrl,\n loginSuccessUrl: loginSuccessUrl,\n targetContainerElement: targetContainerElement,\n displayMode: options.displayMode,\n iframeMode: options.iframeMode,\n logoutCallbackUrl: logoutCallbackUrl,\n framework: \"nextjs\",\n logging: options.logging,\n backendEndpoints: {\n user: userUrl,\n refresh: refreshUrl,\n logout: logoutUrl,\n clearSession: clearSessionUrl,\n },\n onSignOut,\n onRefresh,\n onSignIn,\n onUrlChange: options.onUrlChange,\n initialUser: (!hasSignedOut && options.serverUser) || null,\n initialIdToken: null, // ID token is httpOnly and not accessible\n };\n }, [\n options.disableRefresh,\n options.displayMode,\n options.iframeMode,\n options.logging,\n options.onUrlChange,\n options.serverUser,\n clientId,\n loginInitUrl,\n callbackUrl,\n oauthServer,\n logoutCallbackUrl,\n loginSuccessUrl,\n targetContainerElement,\n userUrl,\n refreshUrl,\n logoutUrl,\n clearSessionUrl,\n basePath,\n hasSignedOut,\n onSignOut,\n onRefresh,\n onSignIn,\n ]);\n\n const createConfigWithOverrides = useMemo(() => {\n return (\n overrides: UseInitialAuthConfigOverrides = {},\n ): GlobalAuthConfig => {\n return {\n ...baseConfig,\n // Override specific properties while keeping the base config\n ...(overrides.displayMode && { displayMode: overrides.displayMode }),\n ...(overrides.iframeMode !== undefined && {\n iframeMode: overrides.iframeMode,\n }),\n ...(overrides.clientId && { clientId: overrides.clientId }),\n ...(overrides.redirectUrl && { redirectUrl: overrides.redirectUrl }),\n ...(overrides.logoutRedirectUrl && {\n logoutRedirectUrl: overrides.logoutRedirectUrl,\n }),\n ...(overrides.targetContainerElement && {\n targetContainerElement: overrides.targetContainerElement,\n }),\n };\n };\n }, [baseConfig]);\n\n return {\n initialConfig: baseConfig,\n createConfigWithOverrides,\n logoutUrl,\n hasSignedOut,\n };\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NextAuthProviderClient.d.ts","sourceRoot":"","sources":["../../../src/nextjs/providers/NextAuthProviderClient.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAIpD,KAAK,0BAA0B,GAAG,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;AAEtE;;;GAGG;AACH,MAAM,WAAW,gCACf,SAAQ,0BAA0B;IAClC,4EAA4E;IAC5E,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,iDAAiD;IACjD,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;CAClC;AAID,eAAO,MAAM,2BAA2B,qDAKrC,gCAAgC,
|
|
1
|
+
{"version":3,"file":"NextAuthProviderClient.d.ts","sourceRoot":"","sources":["../../../src/nextjs/providers/NextAuthProviderClient.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAIpD,KAAK,0BAA0B,GAAG,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;AAEtE;;;GAGG;AACH,MAAM,WAAW,gCACf,SAAQ,0BAA0B;IAClC,4EAA4E;IAC5E,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,iDAAiD;IACjD,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;CAClC;AAID,eAAO,MAAM,2BAA2B,qDAKrC,gCAAgC,4CAkGlC,CAAC"}
|
|
@@ -9,7 +9,7 @@ import { GlobalAuthManager } from "../../reactjs/core/GlobalAuthManager.js";
|
|
|
9
9
|
import { AuthStatusProvider } from "../../shared/providers/AuthStatusContext.js";
|
|
10
10
|
import { ServerUserContext } from "./ServerUserContext.js";
|
|
11
11
|
import { useInitialAuthConfig } from "../../nextjs/hooks/useInitialAuthConfig.js";
|
|
12
|
-
import { useEffect, useRef } from "react";
|
|
12
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
13
13
|
import { usePathname, useRouter } from "next/navigation.js";
|
|
14
14
|
import { loggers } from "../../lib/logger.js";
|
|
15
15
|
// Context to provide server user data immediately to useUser hook
|
|
@@ -19,6 +19,30 @@ export const CivicNextAuthProviderClient = ({ children, serverUser, serverTokens
|
|
|
19
19
|
const { oauthServer, loginSuccessUrl, disableRefresh } = resolvedConfig;
|
|
20
20
|
const pathname = usePathname();
|
|
21
21
|
const previousPathname = useRef(pathname);
|
|
22
|
+
// Router is expected to be stable across renders per Next.js contract, but we
|
|
23
|
+
// read it through a ref so onUrlChange stays referentially stable for the
|
|
24
|
+
// lifetime of the component even if that ever changes. This prevents the
|
|
25
|
+
// reference-instability loop that tore down and rebuilt the OAuth iframe
|
|
26
|
+
// on every render (AUTH-308).
|
|
27
|
+
const routerRef = useRef(router);
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
routerRef.current = router;
|
|
30
|
+
}, [router]);
|
|
31
|
+
const onUrlChange = useCallback((url, source) => {
|
|
32
|
+
switch (source) {
|
|
33
|
+
case "login":
|
|
34
|
+
loggers.nextjs.providers.debug(`[NextAuthProvider] Authentication redirect: ${url}`);
|
|
35
|
+
window.location.href = url;
|
|
36
|
+
break;
|
|
37
|
+
case "login_app":
|
|
38
|
+
loggers.nextjs.providers.debug(`[NextAuthProvider] Login app redirect: ${url}`);
|
|
39
|
+
window.location.href = url;
|
|
40
|
+
break;
|
|
41
|
+
default:
|
|
42
|
+
loggers.nextjs.providers.debug(`[NextAuthProvider] Navigating to: ${url} (source: ${source || "unknown"})`);
|
|
43
|
+
routerRef.current.push(url);
|
|
44
|
+
}
|
|
45
|
+
}, []);
|
|
22
46
|
// Initialize GlobalAuthManager synchronously with server user data
|
|
23
47
|
// This ensures the server user is available immediately when useUser() is called
|
|
24
48
|
const { initialConfig, hasSignedOut } = useInitialAuthConfig({
|
|
@@ -31,22 +55,7 @@ export const CivicNextAuthProviderClient = ({ children, serverUser, serverTokens
|
|
|
31
55
|
targetContainerElement: props.targetContainerElement,
|
|
32
56
|
oauthServer: oauthServer,
|
|
33
57
|
loginSuccessUrl: loginSuccessUrl,
|
|
34
|
-
onUrlChange
|
|
35
|
-
// Handle different URL change sources
|
|
36
|
-
switch (source) {
|
|
37
|
-
case "login":
|
|
38
|
-
console.log(`[NextAuthProvider] Authentication redirect: ${url}`);
|
|
39
|
-
window.location.href = url;
|
|
40
|
-
break;
|
|
41
|
-
case "login_app":
|
|
42
|
-
console.log(`[NextAuthProvider] Login app redirect: ${url}`);
|
|
43
|
-
window.location.href = url;
|
|
44
|
-
break;
|
|
45
|
-
default:
|
|
46
|
-
console.log(`[NextAuthProvider] Navigating to: ${url} (source: ${source || "unknown"})`);
|
|
47
|
-
router.push(url);
|
|
48
|
-
}
|
|
49
|
-
},
|
|
58
|
+
onUrlChange,
|
|
50
59
|
});
|
|
51
60
|
// Initialize auth manager with server-provided data
|
|
52
61
|
useEffect(() => {
|
|
@@ -58,6 +67,7 @@ export const CivicNextAuthProviderClient = ({ children, serverUser, serverTokens
|
|
|
58
67
|
previousPathname.current = pathname;
|
|
59
68
|
await manager.cleanup();
|
|
60
69
|
}
|
|
70
|
+
loggers.nextjs.providers.debug("[NextAuthProvider] initialize effect firing", { pathname, hasSignedOut });
|
|
61
71
|
await manager.initialize(initialConfig);
|
|
62
72
|
}
|
|
63
73
|
catch (error) {
|
|
@@ -70,7 +80,7 @@ export const CivicNextAuthProviderClient = ({ children, serverUser, serverTokens
|
|
|
70
80
|
if (!hasSignedOut) {
|
|
71
81
|
initialize();
|
|
72
82
|
}
|
|
73
|
-
}, [initialConfig,
|
|
83
|
+
}, [initialConfig, pathname, hasSignedOut]);
|
|
74
84
|
return (_jsx(ServerUserContext.Provider, { value: { user: serverUser, tokens: serverTokens }, children: _jsx(AuthStatusProvider, { children: children }) }));
|
|
75
85
|
};
|
|
76
86
|
//# sourceMappingURL=NextAuthProviderClient.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NextAuthProviderClient.js","sourceRoot":"","sources":["../../../src/nextjs/providers/NextAuthProviderClient.tsx"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,YAAY,CAAC;;AAEb;;GAEG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAE9E,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"NextAuthProviderClient.js","sourceRoot":"","sources":["../../../src/nextjs/providers/NextAuthProviderClient.tsx"],"names":[],"mappings":"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","sourcesContent":["/** @jsxImportSource react */\n\"use client\";\n\n/**\n * Client component for NextAuth provider that receives server-provided user data\n */\nimport { resolveAuthConfig } from \"@/nextjs/config.js\";\nimport { GlobalAuthManager } from \"@/reactjs/core/GlobalAuthManager.js\";\nimport { AuthStatusProvider } from \"@/shared/providers/AuthStatusContext.js\";\nimport { ServerUserContext } from \"./ServerUserContext.js\";\nimport { useInitialAuthConfig } from \"@/nextjs/hooks/useInitialAuthConfig.js\";\nimport type { AuthProviderProps } from \"@/shared/providers/types.js\";\nimport { useCallback, useEffect, useRef } from \"react\";\nimport type { User, OAuthTokens } from \"@/types.js\";\nimport { usePathname, useRouter } from \"next/navigation.js\";\nimport { loggers } from \"@/lib/logger.js\";\n\ntype NextCivicAuthProviderProps = Omit<AuthProviderProps, \"clientId\">;\n\n/**\n * Props for the CivicNextAuthProviderClient component.\n * @internal This interface is for internal use - the public API is through CivicAuthProvider.\n */\nexport interface CivicNextAuthProviderClientProps\n extends NextCivicAuthProviderProps {\n /** Server-provided user data for hydration to prevent hydration mismatch */\n serverUser: User | null;\n /** Server-provided OAuth tokens for hydration */\n serverTokens: OAuthTokens | null;\n}\n\n// Context to provide server user data immediately to useUser hook\n\nexport const CivicNextAuthProviderClient = ({\n children,\n serverUser,\n serverTokens,\n ...props\n}: CivicNextAuthProviderClientProps) => {\n const router = useRouter();\n const resolvedConfig = resolveAuthConfig();\n const { oauthServer, loginSuccessUrl, disableRefresh } = resolvedConfig;\n\n const pathname = usePathname();\n const previousPathname = useRef(pathname);\n\n // Router is expected to be stable across renders per Next.js contract, but we\n // read it through a ref so onUrlChange stays referentially stable for the\n // lifetime of the component even if that ever changes. This prevents the\n // reference-instability loop that tore down and rebuilt the OAuth iframe\n // on every render (AUTH-308).\n const routerRef = useRef(router);\n useEffect(() => {\n routerRef.current = router;\n }, [router]);\n\n const onUrlChange = useCallback((url: string, source?: string) => {\n switch (source) {\n case \"login\":\n loggers.nextjs.providers.debug(\n `[NextAuthProvider] Authentication redirect: ${url}`,\n );\n window.location.href = url;\n break;\n case \"login_app\":\n loggers.nextjs.providers.debug(\n `[NextAuthProvider] Login app redirect: ${url}`,\n );\n window.location.href = url;\n break;\n default:\n loggers.nextjs.providers.debug(\n `[NextAuthProvider] Navigating to: ${url} (source: ${source || \"unknown\"})`,\n );\n routerRef.current.push(url);\n }\n }, []);\n\n // Initialize GlobalAuthManager synchronously with server user data\n // This ensures the server user is available immediately when useUser() is called\n const { initialConfig, hasSignedOut } = useInitialAuthConfig({\n disableRefresh,\n logging: props.logging,\n displayMode: props.displayMode || \"iframe\",\n iframeMode: props.iframeMode,\n serverUser: serverUser,\n nonce: props.nonce,\n targetContainerElement: props.targetContainerElement,\n oauthServer: oauthServer,\n loginSuccessUrl: loginSuccessUrl,\n onUrlChange,\n });\n\n // Initialize auth manager with server-provided data\n useEffect(() => {\n const initialize = async () => {\n try {\n const manager = GlobalAuthManager.getInstance();\n\n if (previousPathname.current !== pathname) {\n loggers.nextjs.hooks.debug(\n `[NextAuthProvider] Pathname changed from ${previousPathname.current} to ${pathname}, cleaning auth manager`,\n );\n previousPathname.current = pathname;\n await manager.cleanup();\n }\n\n loggers.nextjs.providers.debug(\n \"[NextAuthProvider] initialize effect firing\",\n { pathname, hasSignedOut },\n );\n\n await manager.initialize(initialConfig);\n } catch (error) {\n console.error(\n \"[NextAuthProvider] Failed to initialize auth manager:\",\n error,\n );\n }\n };\n\n // don't immediately initialize while signing out\n // or we might overwrite the signed-out state the version\n // from the /user endpoint before it has updated\n if (!hasSignedOut) {\n initialize();\n }\n }, [initialConfig, pathname, hasSignedOut]);\n\n return (\n <ServerUserContext.Provider\n value={{ user: serverUser, tokens: serverTokens }}\n >\n <AuthStatusProvider>{children}</AuthStatusProvider>\n </ServerUserContext.Provider>\n );\n};\n"]}
|
|
@@ -159,9 +159,21 @@ declare class GlobalAuthManager {
|
|
|
159
159
|
*/
|
|
160
160
|
resetOnBfcache(): void;
|
|
161
161
|
/**
|
|
162
|
-
* Check if config is the same (for idempotent initialization)
|
|
162
|
+
* Check if structural config is the same (for idempotent initialization).
|
|
163
|
+
*
|
|
164
|
+
* NOTE: Callback references (`onSignIn`/`onSignOut`/`onUrlChange`/...) are
|
|
165
|
+
* intentionally NOT compared here. React renders routinely produce new
|
|
166
|
+
* closure references for callbacks even when the underlying behavior is
|
|
167
|
+
* unchanged; comparing them by reference tore down and rebuilt the OAuth
|
|
168
|
+
* iframe on every render (AUTH-308). Callback swaps are handled via
|
|
169
|
+
* {@link updateCallbacks}.
|
|
163
170
|
*/
|
|
164
171
|
private isSameConfig;
|
|
172
|
+
/**
|
|
173
|
+
* Check whether any callback reference has changed since the last config.
|
|
174
|
+
* Used to decide whether to swap live closures without re-initializing.
|
|
175
|
+
*/
|
|
176
|
+
private haveCallbacksChanged;
|
|
165
177
|
/**
|
|
166
178
|
* Setup event listeners for auth state changes
|
|
167
179
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GlobalAuthManager.d.ts","sourceRoot":"","sources":["../../../src/reactjs/core/GlobalAuthManager.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"GlobalAuthManager.d.ts","sourceRoot":"","sources":["../../../src/reactjs/core/GlobalAuthManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -62,13 +62,29 @@ class GlobalAuthManager {
|
|
|
62
62
|
* Returns the same promise for concurrent calls with same config
|
|
63
63
|
*/
|
|
64
64
|
async initialize(config) {
|
|
65
|
-
// If
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
// If structural config matches, do not tear down the existing auth
|
|
66
|
+
// instance just because callback references have changed (AUTH-308).
|
|
67
|
+
// Swap the live callbacks in place and return the in-flight/resolved
|
|
68
|
+
// initialization promise so the OAuth iframe is not rebuilt.
|
|
69
|
+
if (this.config && this.isSameConfig(config)) {
|
|
70
|
+
if (this.haveCallbacksChanged(config)) {
|
|
71
|
+
this.updateCallbacks({
|
|
72
|
+
onSignIn: config.onSignIn,
|
|
73
|
+
onSignOut: config.onSignOut,
|
|
74
|
+
onUrlChange: config.onUrlChange,
|
|
75
|
+
onRefresh: config.onRefresh,
|
|
76
|
+
onPreSignIn: config.onPreSignIn,
|
|
77
|
+
onPreSignOut: config.onPreSignOut,
|
|
78
|
+
});
|
|
79
|
+
// Update the stored config so future callback-change comparisons
|
|
80
|
+
// are made against the latest references.
|
|
81
|
+
this.config = config;
|
|
82
|
+
}
|
|
83
|
+
if (this.initializationPromise) {
|
|
84
|
+
return this.initializationPromise;
|
|
85
|
+
}
|
|
70
86
|
}
|
|
71
|
-
// If different config, reset everything
|
|
87
|
+
// If different structural config, reset everything
|
|
72
88
|
if (this.config && !this.isSameConfig(config)) {
|
|
73
89
|
this.initializationPromise = null;
|
|
74
90
|
await this.cleanup();
|
|
@@ -318,7 +334,14 @@ class GlobalAuthManager {
|
|
|
318
334
|
}
|
|
319
335
|
}
|
|
320
336
|
/**
|
|
321
|
-
* Check if config is the same (for idempotent initialization)
|
|
337
|
+
* Check if structural config is the same (for idempotent initialization).
|
|
338
|
+
*
|
|
339
|
+
* NOTE: Callback references (`onSignIn`/`onSignOut`/`onUrlChange`/...) are
|
|
340
|
+
* intentionally NOT compared here. React renders routinely produce new
|
|
341
|
+
* closure references for callbacks even when the underlying behavior is
|
|
342
|
+
* unchanged; comparing them by reference tore down and rebuilt the OAuth
|
|
343
|
+
* iframe on every render (AUTH-308). Callback swaps are handled via
|
|
344
|
+
* {@link updateCallbacks}.
|
|
322
345
|
*/
|
|
323
346
|
isSameConfig(newConfig) {
|
|
324
347
|
if (!this.config)
|
|
@@ -326,12 +349,24 @@ class GlobalAuthManager {
|
|
|
326
349
|
return (this.config.clientId === newConfig.clientId &&
|
|
327
350
|
this.config.config?.oauthServer === newConfig.config?.oauthServer &&
|
|
328
351
|
this.config.displayMode === newConfig.displayMode &&
|
|
352
|
+
this.config.iframeMode === newConfig.iframeMode &&
|
|
329
353
|
this.config.nonce === newConfig.nonce &&
|
|
330
354
|
this.config.preloadIframe === newConfig.preloadIframe &&
|
|
331
|
-
this.config.autoRedirect === newConfig.autoRedirect
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
355
|
+
this.config.autoRedirect === newConfig.autoRedirect);
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Check whether any callback reference has changed since the last config.
|
|
359
|
+
* Used to decide whether to swap live closures without re-initializing.
|
|
360
|
+
*/
|
|
361
|
+
haveCallbacksChanged(newConfig) {
|
|
362
|
+
if (!this.config)
|
|
363
|
+
return false;
|
|
364
|
+
return (this.config.onSignIn !== newConfig.onSignIn ||
|
|
365
|
+
this.config.onSignOut !== newConfig.onSignOut ||
|
|
366
|
+
this.config.onUrlChange !== newConfig.onUrlChange ||
|
|
367
|
+
this.config.onRefresh !== newConfig.onRefresh ||
|
|
368
|
+
this.config.onPreSignIn !== newConfig.onPreSignIn ||
|
|
369
|
+
this.config.onPreSignOut !== newConfig.onPreSignOut);
|
|
335
370
|
}
|
|
336
371
|
/**
|
|
337
372
|
* Setup event listeners for auth state changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GlobalAuthManager.js","sourceRoot":"","sources":["../../../src/reactjs/core/GlobalAuthManager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * GlobalAuthManager - Singleton Authentication State Manager\n *\n * This module provides a global singleton that manages authentication state across a React application\n * without requiring React Context providers or prop drilling. It acts as a centralized authentication\n * manager that wraps the CivicAuth vanilla JavaScript library and provides a React-friendly interface.\n *\n * Key Features:\n * - Singleton pattern ensures single auth instance across the entire app\n * - Eliminates need for React Context providers and reduces bundle size\n * - Manages authentication state (user, session, loading, errors)\n * - Handles sign-in/sign-out flows with event-driven updates\n * - Provides idempotent initialization (safe to call multiple times)\n * - Supports multiple React hooks subscribing to the same auth state\n * - Automatic session refresh and user data synchronization\n *\n * Usage:\n * - Initialize once in your app with authentication configuration\n * - Use React hooks (useCivicAuth, useAuth, etc.) to access auth state\n * - The manager handles all underlying CivicAuth SDK interactions\n * - State updates are automatically propagated to all subscribed components\n *\n * This design pattern is particularly useful for:\n * - Large applications with many components needing auth state\n * - Avoiding provider wrapper hell in React component trees\n * - Ensuring consistent auth state across disconnected component hierarchies\n * - Server-side rendering scenarios where providers might be problematic\n */\n\nimport {\n CivicAuth,\n AuthenticationEvents,\n AuthEvent,\n} from \"../../vanillajs/index.js\";\nimport type {\n User,\n Session,\n CivicAuthClientConfig,\n OnSignInResponse,\n OnSignOutResponse,\n} from \"../../vanillajs/index.js\";\nimport type { AuthStorage, FrameworkType } from \"../../types.js\";\nimport type { VanillaJSDisplayMode } from \"../../vanillajs/auth/types/AuthTypes.js\";\nimport type { LoggingConfig } from \"@/vanillajs/auth/types/AuthTypes.js\";\nimport { DEFAULT_AUTH_PROCESS_TIMEOUT } from \"../../vanillajs/auth/types/AuthTypes.js\";\nimport type { BackendEndpoints } from \"@/server/config.js\";\n\n// Event payload interfaces\ninterface SignInCompleteEvent {\n detail?: string;\n redirectUrl?: string;\n}\n\ninterface SignInErrorEvent {\n detail: string;\n}\n\nexport interface GlobalAuthConfig {\n clientId?: string;\n redirectUrl?: string;\n loginUrl?: string;\n config?: {\n oauthServer?: string;\n };\n displayMode?: VanillaJSDisplayMode;\n iframeMode?: \"modal\" | \"embedded\";\n nonce?: string;\n logoutRedirectUrl?: string;\n scopes?: string[];\n authProcessTimeout?: number;\n onRefresh?: (error?: Error) => void;\n onSignIn?: (response: OnSignInResponse) => void | Promise<void>;\n onSignOut?: (response: OnSignOutResponse) => void | Promise<void>;\n onPreSignIn?: (response: OnSignInResponse) => Promise<void>;\n onPreSignOut?: (response: OnSignOutResponse) => Promise<void>;\n onUrlChange?: (url: string, source?: string) => void;\n logging?: LoggingConfig;\n preloadIframe?: boolean;\n autoRedirect?: boolean;\n /** Framework being used (for analytics) - internal use only */\n framework?: FrameworkType;\n backendEndpoints?: BackendEndpoints;\n targetContainerElement?: HTMLElement | string;\n loginSuccessUrl?: string;\n storage?: AuthStorage;\n initialUser?: User | null;\n disableRefresh?: boolean;\n}\n\nexport type AuthStatus =\n | \"authenticated\"\n | \"unauthenticated\"\n | \"authenticating\"\n | \"error\"\n | \"signing_out\";\n\nexport interface GlobalAuthState {\n user: User | null;\n session: Session | null;\n isLoading: boolean;\n authStatus: AuthStatus;\n error: Error | null;\n displayMode?: VanillaJSDisplayMode;\n isPreloaded?: boolean;\n}\n\ntype StateListener = (state: GlobalAuthState) => void;\n\n/**\n * Global singleton that manages CivicAuth instance for React hooks\n * Eliminates the need for React providers\n */\nclass GlobalAuthManager {\n private static instance: GlobalAuthManager | null = null;\n private auth: CivicAuth | null = null;\n private events: AuthenticationEvents | null = null;\n private config: GlobalAuthConfig | null = null;\n private listeners = new Set<StateListener>();\n private callbacks: {\n onSignIn?: (response: OnSignInResponse) => void | Promise<void>;\n onSignOut?: (response: OnSignOutResponse) => void | Promise<void>;\n onUrlChange?: (url: string, source?: string) => void;\n onRefresh?: (error?: Error) => void;\n onPreSignIn?: (response: OnSignInResponse) => void | Promise<void>;\n onPreSignOut?: (response: OnSignOutResponse) => void | Promise<void>;\n } = {};\n private initializationPromise: Promise<void> | null = null;\n\n private state: GlobalAuthState = {\n user: null,\n session: null,\n isLoading: false,\n authStatus: \"unauthenticated\",\n error: null,\n displayMode: undefined,\n };\n\n private constructor() {\n // Private constructor for singleton\n }\n\n static getInstance(): GlobalAuthManager {\n if (!GlobalAuthManager.instance) {\n GlobalAuthManager.instance = new GlobalAuthManager();\n }\n return GlobalAuthManager.instance;\n }\n\n /**\n * Initialize auth with config (idempotent)\n * Returns the same promise for concurrent calls with same config\n */\n async initialize(config: GlobalAuthConfig): Promise<void> {\n // If we have a promise and same config, return existing promise\n if (\n this.initializationPromise &&\n this.config &&\n this.isSameConfig(config)\n ) {\n return this.initializationPromise;\n }\n\n // If different config, reset everything\n if (this.config && !this.isSameConfig(config)) {\n this.initializationPromise = null;\n await this.cleanup();\n }\n\n // Create new initialization promise if needed\n if (!this.initializationPromise) {\n this.initializationPromise = this._doInitialize(config);\n }\n\n return this.initializationPromise;\n }\n\n private defaultOnUrlChange(url: string, source?: string) {\n console.log(\"onUrlChange triggering window redirect\", { url, source });\n window.location.href = url;\n }\n\n public updateCallbacks(callbacks: {\n onSignIn?: (response: OnSignInResponse) => void | Promise<void>;\n onSignOut?: (response: OnSignOutResponse) => void | Promise<void>;\n onUrlChange?: (url: string, source?: string) => void;\n onRefresh?: (error?: Error) => void;\n onPreSignIn?: (response: OnSignInResponse) => void | Promise<void>;\n onPreSignOut?: (response: OnSignOutResponse) => void | Promise<void>;\n }): void {\n this.callbacks = {\n ...this.callbacks,\n ...callbacks,\n };\n }\n /**\n * Private method that does the actual initialization work\n */\n private async _doInitialize(config: GlobalAuthConfig): Promise<void> {\n this.config = config;\n this.callbacks = {\n onSignIn: config.onSignIn,\n onSignOut: config.onSignOut,\n onUrlChange: config.onUrlChange || this.defaultOnUrlChange,\n onRefresh: config.onRefresh,\n onPreSignIn: config.onPreSignIn || this.callbacks.onPreSignIn,\n onPreSignOut: config.onPreSignOut || this.callbacks.onPreSignOut,\n };\n this.setState({\n isLoading: true,\n error: null,\n ...(this.config.initialUser && this.state.authStatus !== \"signing_out\"\n ? { user: this.config.initialUser, authStatus: \"authenticated\" }\n : {}), // Set initial user if provided\n });\n\n try {\n this.events = new AuthenticationEvents();\n this.setupEventListeners();\n\n // Build base config common to both branches\n const baseConfig = {\n ...config,\n oauthServerBaseUrl: config.config?.oauthServer,\n scopes: config.scopes || [\n \"openid\",\n \"profile\",\n \"email\",\n \"offline_access\",\n ],\n displayMode: config.displayMode || \"iframe\",\n iframeDisplayMode: config.iframeMode || \"modal\",\n nonce: config.nonce,\n authProcessTimeout:\n config.authProcessTimeout || DEFAULT_AUTH_PROCESS_TIMEOUT,\n preloadIframe: config.preloadIframe,\n autoRedirect: config.autoRedirect,\n events: this.events,\n framework: config.framework,\n storageAdapter: config.storage,\n };\n\n // Build auth config based on discriminated union requirements\n const authConfig: CivicAuthClientConfig = config.loginUrl\n ? {\n // Backend integration mode: loginUrl required, clientId optional\n ...baseConfig,\n loginUrl: config.loginUrl,\n clientId: config.clientId,\n }\n : {\n // Standard OAuth mode: clientId required, loginUrl optional\n ...baseConfig,\n clientId: config.clientId!,\n loginUrl: config.loginUrl,\n };\n\n // Only add redirectUrl if provided\n if (config.redirectUrl) {\n authConfig.redirectUrl = config.redirectUrl;\n }\n\n // Only add logoutRedirectUrl if provided\n if (config.logoutRedirectUrl) {\n authConfig.logoutRedirectUrl = config.logoutRedirectUrl;\n }\n\n // Only add loginSuccessUrl if provided\n if (config.loginSuccessUrl) {\n authConfig.loginSuccessUrl = config.loginSuccessUrl;\n }\n\n this.auth = await CivicAuth.create(authConfig);\n // Check initial auth state\n const isAuthenticated = await this.auth.isAuthenticated();\n\n if (isAuthenticated) {\n await this.updateUserAndSession();\n this.setState({ authStatus: \"authenticated\" });\n } else {\n this.setState({ authStatus: \"unauthenticated\" });\n\n // Note: Preloading is now handled automatically by CivicAuth based on config.preloadIframe\n }\n\n this.setState({\n isLoading: false,\n displayMode: config.displayMode,\n });\n } catch (error) {\n // Reset promise on error so it can be retried\n this.initializationPromise = null;\n\n const authError =\n error instanceof Error\n ? error\n : new Error(\"Auth initialization failed\");\n this.setState({\n error: authError,\n authStatus: \"error\",\n isLoading: false,\n });\n throw authError;\n }\n }\n\n /**\n * Subscribe to state changes\n */\n subscribe(listener: StateListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /**\n * Get current state\n */\n getState(): GlobalAuthState {\n return { ...this.state };\n }\n\n /**\n * Get current configuration\n * Returns the current config or null if not initialized\n */\n getConfig(): GlobalAuthConfig | null {\n return this.config ? { ...this.config } : null;\n }\n\n /**\n * Sign in\n */\n async signIn(): Promise<{ user: User }> {\n if (!this.auth) {\n await this.initialize(this.config || {});\n }\n if (!this.auth) {\n throw new Error(\"Auth not initialized\");\n }\n\n const authResult = await this.auth.startAuthentication();\n\n // If authentication returned a user, use it directly\n if (authResult.user) {\n await this.updateUserAndSession();\n this.setState({\n user: authResult.user,\n authStatus: \"authenticated\",\n error: null,\n });\n return { user: authResult.user };\n }\n\n // Fallback: try to refresh user and session data\n await this.updateUserAndSession();\n\n // Check the current state for the user after refresh\n const currentState = this.getState();\n\n if (!currentState.user) {\n throw new Error(\"Authentication succeeded but no user was returned\");\n }\n\n // Return the user object from current state\n return { user: currentState.user };\n }\n\n /**\n * Sign out\n */\n async signOut(): Promise<void> {\n if (!this.auth) {\n throw new Error(\"Auth not initialized\");\n }\n if (this.state.authStatus === \"unauthenticated\") {\n // Already signed out, no-op\n return;\n }\n await this.auth.logout();\n this.setState({\n user: null,\n session: null,\n authStatus: \"unauthenticated\",\n });\n }\n\n /**\n * Check if authentication is preloaded and ready for instant sign-in\n * @returns True if an iframe is preloaded and ready\n */\n isAuthenticationPreloaded(): boolean {\n return this.auth?.isAuthenticationPreloaded() ?? false;\n }\n\n /**\n * Enable or disable iframe preloading\n */\n setPreloadEnabled(enabled: boolean): void {\n if (!this.auth) {\n throw new Error(\"Auth not initialized\");\n }\n this.auth.setPreloadEnabled(enabled);\n }\n\n /**\n * Check if iframe preloading is enabled\n */\n getPreloadEnabled(): boolean {\n return this.auth?.getPreloadEnabled() ?? true;\n }\n\n /**\n * Reloads embedded authentication interface\n *\n * This method is specifically designed for embedded mode scenarios where the iframe\n * needs to be recreated after navigation or DOM changes. It delegates to the\n * underlying CivicAuth instance's reloadEmbedded method.\n *\n * @returns Promise that resolves when the embedded iframe is created\n * @throws {Error} If not in embedded mode or if auth is not initialized\n */\n async reloadEmbedded(): Promise<void> {\n if (!this.auth) {\n throw new Error(\"Auth not initialized. Call initialize() first.\");\n }\n\n return this.auth.reloadEmbedded();\n }\n\n /**\n * Reset authentication state when detected from back-forward cache (bfcache)\n * This fixes issues where sign-in button becomes unclickable after back navigation\n */\n resetOnBfcache(): void {\n if (!this.auth) return;\n\n // Reset internal CivicAuth state first\n this.auth.resetOnBfcache();\n\n // Reset auth state to unauthenticated to allow new sign-in attempts\n this.setState({\n authStatus: \"unauthenticated\",\n isLoading: false,\n error: null,\n user: null,\n session: null,\n });\n\n // Ensure iframe preloading state is refreshed if needed\n if (this.getPreloadEnabled()) {\n this.auth.setPreloadEnabled(true);\n }\n }\n\n /**\n * Check if config is the same (for idempotent initialization)\n */\n private isSameConfig(newConfig: GlobalAuthConfig): boolean {\n if (!this.config) return false;\n return (\n this.config.clientId === newConfig.clientId &&\n this.config.config?.oauthServer === newConfig.config?.oauthServer &&\n this.config.displayMode === newConfig.displayMode &&\n this.config.nonce === newConfig.nonce &&\n this.config.preloadIframe === newConfig.preloadIframe &&\n this.config.autoRedirect === newConfig.autoRedirect &&\n this.config?.onSignIn === newConfig?.onSignIn &&\n this.config?.onSignOut === newConfig?.onSignOut &&\n this.config?.onUrlChange === newConfig?.onUrlChange\n );\n }\n\n /**\n * Setup event listeners for auth state changes\n */\n private setupEventListeners(): void {\n if (!this.events) return;\n\n this.events.on(AuthEvent.SIGN_IN_STARTED, () => {\n this.setState({\n isLoading: true,\n authStatus: \"authenticating\",\n error: null,\n });\n });\n\n this.events.on(AuthEvent.TOKEN_REFRESH_COMPLETE, () => {\n this.setState({\n isLoading: false,\n authStatus: \"authenticated\",\n });\n this.updateUserAndSession();\n this.callbacks.onRefresh?.();\n });\n\n this.events.on(\n AuthEvent.SIGN_IN_COMPLETE,\n async (event?: SignInCompleteEvent) => {\n this.setState({\n isLoading: false,\n authStatus: \"authenticated\",\n error: null,\n });\n this.updateUserAndSession();\n await this.callbacks.onPreSignIn?.({\n user: this.state.user,\n session: this.state.session,\n redirectUrl: event?.redirectUrl,\n });\n await this.callbacks.onSignIn?.({\n user: this.state.user,\n session: this.state.session,\n redirectUrl: event?.redirectUrl,\n });\n },\n );\n\n this.events.on(\n AuthEvent.SIGN_IN_ERROR,\n async (event?: SignInErrorEvent) => {\n const errorDetail = event?.detail || \"Authentication failed\";\n const authError = new Error(errorDetail);\n this.setState({\n isLoading: false,\n authStatus: \"error\",\n error: authError,\n });\n await this.callbacks.onPreSignIn?.({\n error: authError,\n });\n await this.callbacks.onSignIn?.({ error: authError });\n },\n );\n\n this.events.on(AuthEvent.SIGN_OUT_STARTED, () => {\n this.setState({\n isLoading: true,\n authStatus: \"signing_out\",\n error: null,\n });\n });\n\n this.events.on(AuthEvent.SIGN_OUT_COMPLETE, async () => {\n this.setState({\n isLoading: false,\n authStatus: \"unauthenticated\",\n user: null,\n session: null,\n error: null,\n });\n await this.callbacks.onPreSignOut?.({});\n await this.callbacks.onSignOut?.({});\n // if we have a logoutRedirectUrl in config, and it's different from current URL, load it\n if (this.config?.logoutRedirectUrl) {\n const currentPathAndQuery =\n window.location.pathname + window.location.search;\n\n // Parse the logout redirect URL to get its path and query\n const logoutUrl = new URL(\n this.config.logoutRedirectUrl,\n window.location.origin,\n );\n const logoutPathAndQuery = logoutUrl.pathname + logoutUrl.search;\n\n // Only redirect if current path + query is different from logout redirect URL\n if (currentPathAndQuery !== logoutPathAndQuery) {\n window.location.href = this.config.logoutRedirectUrl;\n }\n }\n });\n\n this.events.on(AuthEvent.SIGN_OUT_ERROR, async (error?: Error) => {\n const signOutError =\n error instanceof Error ? error : new Error(\"Sign-out failed\");\n this.setState({\n isLoading: false,\n authStatus: \"error\",\n error: signOutError,\n });\n await this.callbacks.onPreSignOut?.({ error: signOutError });\n await this.callbacks.onSignOut?.({ error: signOutError });\n });\n\n this.events.on(AuthEvent.USER_SESSION_CHANGED, () => {\n // give any pending operations a moment to complete before updating\n setTimeout(() => {\n this.updateUserAndSession();\n }, 100);\n });\n\n this.events.on(\n AuthEvent.URL_CHANGE,\n (event?: { detail?: string; url?: string; source?: string }) => {\n this.setState({\n authStatus: \"authenticating\", // Keep as authenticating since we're redirecting\n error: null,\n });\n // Call custom URL change handler if provided\n if (event?.url && this.callbacks.onUrlChange) {\n this.callbacks.onUrlChange(event.url, event.source);\n }\n },\n );\n }\n\n /**\n * Refresh user and session data\n */\n private async updateUserAndSession(): Promise<void> {\n if (!this.auth) return;\n\n try {\n const [session, user] = await Promise.all([\n this.auth.getCurrentSession(),\n this.auth.getCurrentUser(),\n ]);\n\n this.setState({ session, user });\n } catch (error) {\n const sessionError =\n error instanceof Error ? error : new Error(\"Failed to get session\");\n this.setState({ error: sessionError });\n }\n }\n\n /**\n * Update state and notify listeners\n */\n private setState(updates: Partial<GlobalAuthState>): void {\n this.state = { ...this.state, ...updates };\n this.listeners.forEach((listener) => listener(this.state));\n }\n\n /**\n * Cleanup auth instance\n */\n public async cleanup(): Promise<void> {\n if (this.auth) {\n await this.auth.destroy();\n this.auth = null;\n }\n this.events = null;\n this.config = null;\n this.initializationPromise = null; // Reset promise for clean re-initialization\n }\n}\n\nexport { GlobalAuthManager };\n"]}
|
|
1
|
+
{"version":3,"file":"GlobalAuthManager.js","sourceRoot":"","sources":["../../../src/reactjs/core/GlobalAuthManager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * GlobalAuthManager - Singleton Authentication State Manager\n *\n * This module provides a global singleton that manages authentication state across a React application\n * without requiring React Context providers or prop drilling. It acts as a centralized authentication\n * manager that wraps the CivicAuth vanilla JavaScript library and provides a React-friendly interface.\n *\n * Key Features:\n * - Singleton pattern ensures single auth instance across the entire app\n * - Eliminates need for React Context providers and reduces bundle size\n * - Manages authentication state (user, session, loading, errors)\n * - Handles sign-in/sign-out flows with event-driven updates\n * - Provides idempotent initialization (safe to call multiple times)\n * - Supports multiple React hooks subscribing to the same auth state\n * - Automatic session refresh and user data synchronization\n *\n * Usage:\n * - Initialize once in your app with authentication configuration\n * - Use React hooks (useCivicAuth, useAuth, etc.) to access auth state\n * - The manager handles all underlying CivicAuth SDK interactions\n * - State updates are automatically propagated to all subscribed components\n *\n * This design pattern is particularly useful for:\n * - Large applications with many components needing auth state\n * - Avoiding provider wrapper hell in React component trees\n * - Ensuring consistent auth state across disconnected component hierarchies\n * - Server-side rendering scenarios where providers might be problematic\n */\n\nimport {\n CivicAuth,\n AuthenticationEvents,\n AuthEvent,\n} from \"../../vanillajs/index.js\";\nimport type {\n User,\n Session,\n CivicAuthClientConfig,\n OnSignInResponse,\n OnSignOutResponse,\n} from \"../../vanillajs/index.js\";\nimport type { AuthStorage, FrameworkType } from \"../../types.js\";\nimport type { VanillaJSDisplayMode } from \"../../vanillajs/auth/types/AuthTypes.js\";\nimport type { LoggingConfig } from \"@/vanillajs/auth/types/AuthTypes.js\";\nimport { DEFAULT_AUTH_PROCESS_TIMEOUT } from \"../../vanillajs/auth/types/AuthTypes.js\";\nimport type { BackendEndpoints } from \"@/server/config.js\";\n\n// Event payload interfaces\ninterface SignInCompleteEvent {\n detail?: string;\n redirectUrl?: string;\n}\n\ninterface SignInErrorEvent {\n detail: string;\n}\n\nexport interface GlobalAuthConfig {\n clientId?: string;\n redirectUrl?: string;\n loginUrl?: string;\n config?: {\n oauthServer?: string;\n };\n displayMode?: VanillaJSDisplayMode;\n iframeMode?: \"modal\" | \"embedded\";\n nonce?: string;\n logoutRedirectUrl?: string;\n scopes?: string[];\n authProcessTimeout?: number;\n onRefresh?: (error?: Error) => void;\n onSignIn?: (response: OnSignInResponse) => void | Promise<void>;\n onSignOut?: (response: OnSignOutResponse) => void | Promise<void>;\n onPreSignIn?: (response: OnSignInResponse) => Promise<void>;\n onPreSignOut?: (response: OnSignOutResponse) => Promise<void>;\n onUrlChange?: (url: string, source?: string) => void;\n logging?: LoggingConfig;\n preloadIframe?: boolean;\n autoRedirect?: boolean;\n /** Framework being used (for analytics) - internal use only */\n framework?: FrameworkType;\n backendEndpoints?: BackendEndpoints;\n targetContainerElement?: HTMLElement | string;\n loginSuccessUrl?: string;\n storage?: AuthStorage;\n initialUser?: User | null;\n disableRefresh?: boolean;\n}\n\nexport type AuthStatus =\n | \"authenticated\"\n | \"unauthenticated\"\n | \"authenticating\"\n | \"error\"\n | \"signing_out\";\n\nexport interface GlobalAuthState {\n user: User | null;\n session: Session | null;\n isLoading: boolean;\n authStatus: AuthStatus;\n error: Error | null;\n displayMode?: VanillaJSDisplayMode;\n isPreloaded?: boolean;\n}\n\ntype StateListener = (state: GlobalAuthState) => void;\n\n/**\n * Global singleton that manages CivicAuth instance for React hooks\n * Eliminates the need for React providers\n */\nclass GlobalAuthManager {\n private static instance: GlobalAuthManager | null = null;\n private auth: CivicAuth | null = null;\n private events: AuthenticationEvents | null = null;\n private config: GlobalAuthConfig | null = null;\n private listeners = new Set<StateListener>();\n private callbacks: {\n onSignIn?: (response: OnSignInResponse) => void | Promise<void>;\n onSignOut?: (response: OnSignOutResponse) => void | Promise<void>;\n onUrlChange?: (url: string, source?: string) => void;\n onRefresh?: (error?: Error) => void;\n onPreSignIn?: (response: OnSignInResponse) => void | Promise<void>;\n onPreSignOut?: (response: OnSignOutResponse) => void | Promise<void>;\n } = {};\n private initializationPromise: Promise<void> | null = null;\n\n private state: GlobalAuthState = {\n user: null,\n session: null,\n isLoading: false,\n authStatus: \"unauthenticated\",\n error: null,\n displayMode: undefined,\n };\n\n private constructor() {\n // Private constructor for singleton\n }\n\n static getInstance(): GlobalAuthManager {\n if (!GlobalAuthManager.instance) {\n GlobalAuthManager.instance = new GlobalAuthManager();\n }\n return GlobalAuthManager.instance;\n }\n\n /**\n * Initialize auth with config (idempotent)\n * Returns the same promise for concurrent calls with same config\n */\n async initialize(config: GlobalAuthConfig): Promise<void> {\n // If structural config matches, do not tear down the existing auth\n // instance just because callback references have changed (AUTH-308).\n // Swap the live callbacks in place and return the in-flight/resolved\n // initialization promise so the OAuth iframe is not rebuilt.\n if (this.config && this.isSameConfig(config)) {\n if (this.haveCallbacksChanged(config)) {\n this.updateCallbacks({\n onSignIn: config.onSignIn,\n onSignOut: config.onSignOut,\n onUrlChange: config.onUrlChange,\n onRefresh: config.onRefresh,\n onPreSignIn: config.onPreSignIn,\n onPreSignOut: config.onPreSignOut,\n });\n // Update the stored config so future callback-change comparisons\n // are made against the latest references.\n this.config = config;\n }\n if (this.initializationPromise) {\n return this.initializationPromise;\n }\n }\n\n // If different structural config, reset everything\n if (this.config && !this.isSameConfig(config)) {\n this.initializationPromise = null;\n await this.cleanup();\n }\n\n // Create new initialization promise if needed\n if (!this.initializationPromise) {\n this.initializationPromise = this._doInitialize(config);\n }\n\n return this.initializationPromise;\n }\n\n private defaultOnUrlChange(url: string, source?: string) {\n console.log(\"onUrlChange triggering window redirect\", { url, source });\n window.location.href = url;\n }\n\n public updateCallbacks(callbacks: {\n onSignIn?: (response: OnSignInResponse) => void | Promise<void>;\n onSignOut?: (response: OnSignOutResponse) => void | Promise<void>;\n onUrlChange?: (url: string, source?: string) => void;\n onRefresh?: (error?: Error) => void;\n onPreSignIn?: (response: OnSignInResponse) => void | Promise<void>;\n onPreSignOut?: (response: OnSignOutResponse) => void | Promise<void>;\n }): void {\n this.callbacks = {\n ...this.callbacks,\n ...callbacks,\n };\n }\n /**\n * Private method that does the actual initialization work\n */\n private async _doInitialize(config: GlobalAuthConfig): Promise<void> {\n this.config = config;\n this.callbacks = {\n onSignIn: config.onSignIn,\n onSignOut: config.onSignOut,\n onUrlChange: config.onUrlChange || this.defaultOnUrlChange,\n onRefresh: config.onRefresh,\n onPreSignIn: config.onPreSignIn || this.callbacks.onPreSignIn,\n onPreSignOut: config.onPreSignOut || this.callbacks.onPreSignOut,\n };\n this.setState({\n isLoading: true,\n error: null,\n ...(this.config.initialUser && this.state.authStatus !== \"signing_out\"\n ? { user: this.config.initialUser, authStatus: \"authenticated\" }\n : {}), // Set initial user if provided\n });\n\n try {\n this.events = new AuthenticationEvents();\n this.setupEventListeners();\n\n // Build base config common to both branches\n const baseConfig = {\n ...config,\n oauthServerBaseUrl: config.config?.oauthServer,\n scopes: config.scopes || [\n \"openid\",\n \"profile\",\n \"email\",\n \"offline_access\",\n ],\n displayMode: config.displayMode || \"iframe\",\n iframeDisplayMode: config.iframeMode || \"modal\",\n nonce: config.nonce,\n authProcessTimeout:\n config.authProcessTimeout || DEFAULT_AUTH_PROCESS_TIMEOUT,\n preloadIframe: config.preloadIframe,\n autoRedirect: config.autoRedirect,\n events: this.events,\n framework: config.framework,\n storageAdapter: config.storage,\n };\n\n // Build auth config based on discriminated union requirements\n const authConfig: CivicAuthClientConfig = config.loginUrl\n ? {\n // Backend integration mode: loginUrl required, clientId optional\n ...baseConfig,\n loginUrl: config.loginUrl,\n clientId: config.clientId,\n }\n : {\n // Standard OAuth mode: clientId required, loginUrl optional\n ...baseConfig,\n clientId: config.clientId!,\n loginUrl: config.loginUrl,\n };\n\n // Only add redirectUrl if provided\n if (config.redirectUrl) {\n authConfig.redirectUrl = config.redirectUrl;\n }\n\n // Only add logoutRedirectUrl if provided\n if (config.logoutRedirectUrl) {\n authConfig.logoutRedirectUrl = config.logoutRedirectUrl;\n }\n\n // Only add loginSuccessUrl if provided\n if (config.loginSuccessUrl) {\n authConfig.loginSuccessUrl = config.loginSuccessUrl;\n }\n\n this.auth = await CivicAuth.create(authConfig);\n // Check initial auth state\n const isAuthenticated = await this.auth.isAuthenticated();\n\n if (isAuthenticated) {\n await this.updateUserAndSession();\n this.setState({ authStatus: \"authenticated\" });\n } else {\n this.setState({ authStatus: \"unauthenticated\" });\n\n // Note: Preloading is now handled automatically by CivicAuth based on config.preloadIframe\n }\n\n this.setState({\n isLoading: false,\n displayMode: config.displayMode,\n });\n } catch (error) {\n // Reset promise on error so it can be retried\n this.initializationPromise = null;\n\n const authError =\n error instanceof Error\n ? error\n : new Error(\"Auth initialization failed\");\n this.setState({\n error: authError,\n authStatus: \"error\",\n isLoading: false,\n });\n throw authError;\n }\n }\n\n /**\n * Subscribe to state changes\n */\n subscribe(listener: StateListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /**\n * Get current state\n */\n getState(): GlobalAuthState {\n return { ...this.state };\n }\n\n /**\n * Get current configuration\n * Returns the current config or null if not initialized\n */\n getConfig(): GlobalAuthConfig | null {\n return this.config ? { ...this.config } : null;\n }\n\n /**\n * Sign in\n */\n async signIn(): Promise<{ user: User }> {\n if (!this.auth) {\n await this.initialize(this.config || {});\n }\n if (!this.auth) {\n throw new Error(\"Auth not initialized\");\n }\n\n const authResult = await this.auth.startAuthentication();\n\n // If authentication returned a user, use it directly\n if (authResult.user) {\n await this.updateUserAndSession();\n this.setState({\n user: authResult.user,\n authStatus: \"authenticated\",\n error: null,\n });\n return { user: authResult.user };\n }\n\n // Fallback: try to refresh user and session data\n await this.updateUserAndSession();\n\n // Check the current state for the user after refresh\n const currentState = this.getState();\n\n if (!currentState.user) {\n throw new Error(\"Authentication succeeded but no user was returned\");\n }\n\n // Return the user object from current state\n return { user: currentState.user };\n }\n\n /**\n * Sign out\n */\n async signOut(): Promise<void> {\n if (!this.auth) {\n throw new Error(\"Auth not initialized\");\n }\n if (this.state.authStatus === \"unauthenticated\") {\n // Already signed out, no-op\n return;\n }\n await this.auth.logout();\n this.setState({\n user: null,\n session: null,\n authStatus: \"unauthenticated\",\n });\n }\n\n /**\n * Check if authentication is preloaded and ready for instant sign-in\n * @returns True if an iframe is preloaded and ready\n */\n isAuthenticationPreloaded(): boolean {\n return this.auth?.isAuthenticationPreloaded() ?? false;\n }\n\n /**\n * Enable or disable iframe preloading\n */\n setPreloadEnabled(enabled: boolean): void {\n if (!this.auth) {\n throw new Error(\"Auth not initialized\");\n }\n this.auth.setPreloadEnabled(enabled);\n }\n\n /**\n * Check if iframe preloading is enabled\n */\n getPreloadEnabled(): boolean {\n return this.auth?.getPreloadEnabled() ?? true;\n }\n\n /**\n * Reloads embedded authentication interface\n *\n * This method is specifically designed for embedded mode scenarios where the iframe\n * needs to be recreated after navigation or DOM changes. It delegates to the\n * underlying CivicAuth instance's reloadEmbedded method.\n *\n * @returns Promise that resolves when the embedded iframe is created\n * @throws {Error} If not in embedded mode or if auth is not initialized\n */\n async reloadEmbedded(): Promise<void> {\n if (!this.auth) {\n throw new Error(\"Auth not initialized. Call initialize() first.\");\n }\n\n return this.auth.reloadEmbedded();\n }\n\n /**\n * Reset authentication state when detected from back-forward cache (bfcache)\n * This fixes issues where sign-in button becomes unclickable after back navigation\n */\n resetOnBfcache(): void {\n if (!this.auth) return;\n\n // Reset internal CivicAuth state first\n this.auth.resetOnBfcache();\n\n // Reset auth state to unauthenticated to allow new sign-in attempts\n this.setState({\n authStatus: \"unauthenticated\",\n isLoading: false,\n error: null,\n user: null,\n session: null,\n });\n\n // Ensure iframe preloading state is refreshed if needed\n if (this.getPreloadEnabled()) {\n this.auth.setPreloadEnabled(true);\n }\n }\n\n /**\n * Check if structural config is the same (for idempotent initialization).\n *\n * NOTE: Callback references (`onSignIn`/`onSignOut`/`onUrlChange`/...) are\n * intentionally NOT compared here. React renders routinely produce new\n * closure references for callbacks even when the underlying behavior is\n * unchanged; comparing them by reference tore down and rebuilt the OAuth\n * iframe on every render (AUTH-308). Callback swaps are handled via\n * {@link updateCallbacks}.\n */\n private isSameConfig(newConfig: GlobalAuthConfig): boolean {\n if (!this.config) return false;\n return (\n this.config.clientId === newConfig.clientId &&\n this.config.config?.oauthServer === newConfig.config?.oauthServer &&\n this.config.displayMode === newConfig.displayMode &&\n this.config.iframeMode === newConfig.iframeMode &&\n this.config.nonce === newConfig.nonce &&\n this.config.preloadIframe === newConfig.preloadIframe &&\n this.config.autoRedirect === newConfig.autoRedirect\n );\n }\n\n /**\n * Check whether any callback reference has changed since the last config.\n * Used to decide whether to swap live closures without re-initializing.\n */\n private haveCallbacksChanged(newConfig: GlobalAuthConfig): boolean {\n if (!this.config) return false;\n return (\n this.config.onSignIn !== newConfig.onSignIn ||\n this.config.onSignOut !== newConfig.onSignOut ||\n this.config.onUrlChange !== newConfig.onUrlChange ||\n this.config.onRefresh !== newConfig.onRefresh ||\n this.config.onPreSignIn !== newConfig.onPreSignIn ||\n this.config.onPreSignOut !== newConfig.onPreSignOut\n );\n }\n\n /**\n * Setup event listeners for auth state changes\n */\n private setupEventListeners(): void {\n if (!this.events) return;\n\n this.events.on(AuthEvent.SIGN_IN_STARTED, () => {\n this.setState({\n isLoading: true,\n authStatus: \"authenticating\",\n error: null,\n });\n });\n\n this.events.on(AuthEvent.TOKEN_REFRESH_COMPLETE, () => {\n this.setState({\n isLoading: false,\n authStatus: \"authenticated\",\n });\n this.updateUserAndSession();\n this.callbacks.onRefresh?.();\n });\n\n this.events.on(\n AuthEvent.SIGN_IN_COMPLETE,\n async (event?: SignInCompleteEvent) => {\n this.setState({\n isLoading: false,\n authStatus: \"authenticated\",\n error: null,\n });\n this.updateUserAndSession();\n await this.callbacks.onPreSignIn?.({\n user: this.state.user,\n session: this.state.session,\n redirectUrl: event?.redirectUrl,\n });\n await this.callbacks.onSignIn?.({\n user: this.state.user,\n session: this.state.session,\n redirectUrl: event?.redirectUrl,\n });\n },\n );\n\n this.events.on(\n AuthEvent.SIGN_IN_ERROR,\n async (event?: SignInErrorEvent) => {\n const errorDetail = event?.detail || \"Authentication failed\";\n const authError = new Error(errorDetail);\n this.setState({\n isLoading: false,\n authStatus: \"error\",\n error: authError,\n });\n await this.callbacks.onPreSignIn?.({\n error: authError,\n });\n await this.callbacks.onSignIn?.({ error: authError });\n },\n );\n\n this.events.on(AuthEvent.SIGN_OUT_STARTED, () => {\n this.setState({\n isLoading: true,\n authStatus: \"signing_out\",\n error: null,\n });\n });\n\n this.events.on(AuthEvent.SIGN_OUT_COMPLETE, async () => {\n this.setState({\n isLoading: false,\n authStatus: \"unauthenticated\",\n user: null,\n session: null,\n error: null,\n });\n await this.callbacks.onPreSignOut?.({});\n await this.callbacks.onSignOut?.({});\n // if we have a logoutRedirectUrl in config, and it's different from current URL, load it\n if (this.config?.logoutRedirectUrl) {\n const currentPathAndQuery =\n window.location.pathname + window.location.search;\n\n // Parse the logout redirect URL to get its path and query\n const logoutUrl = new URL(\n this.config.logoutRedirectUrl,\n window.location.origin,\n );\n const logoutPathAndQuery = logoutUrl.pathname + logoutUrl.search;\n\n // Only redirect if current path + query is different from logout redirect URL\n if (currentPathAndQuery !== logoutPathAndQuery) {\n window.location.href = this.config.logoutRedirectUrl;\n }\n }\n });\n\n this.events.on(AuthEvent.SIGN_OUT_ERROR, async (error?: Error) => {\n const signOutError =\n error instanceof Error ? error : new Error(\"Sign-out failed\");\n this.setState({\n isLoading: false,\n authStatus: \"error\",\n error: signOutError,\n });\n await this.callbacks.onPreSignOut?.({ error: signOutError });\n await this.callbacks.onSignOut?.({ error: signOutError });\n });\n\n this.events.on(AuthEvent.USER_SESSION_CHANGED, () => {\n // give any pending operations a moment to complete before updating\n setTimeout(() => {\n this.updateUserAndSession();\n }, 100);\n });\n\n this.events.on(\n AuthEvent.URL_CHANGE,\n (event?: { detail?: string; url?: string; source?: string }) => {\n this.setState({\n authStatus: \"authenticating\", // Keep as authenticating since we're redirecting\n error: null,\n });\n // Call custom URL change handler if provided\n if (event?.url && this.callbacks.onUrlChange) {\n this.callbacks.onUrlChange(event.url, event.source);\n }\n },\n );\n }\n\n /**\n * Refresh user and session data\n */\n private async updateUserAndSession(): Promise<void> {\n if (!this.auth) return;\n\n try {\n const [session, user] = await Promise.all([\n this.auth.getCurrentSession(),\n this.auth.getCurrentUser(),\n ]);\n\n this.setState({ session, user });\n } catch (error) {\n const sessionError =\n error instanceof Error ? error : new Error(\"Failed to get session\");\n this.setState({ error: sessionError });\n }\n }\n\n /**\n * Update state and notify listeners\n */\n private setState(updates: Partial<GlobalAuthState>): void {\n this.state = { ...this.state, ...updates };\n this.listeners.forEach((listener) => listener(this.state));\n }\n\n /**\n * Cleanup auth instance\n */\n public async cleanup(): Promise<void> {\n if (this.auth) {\n await this.auth.destroy();\n this.auth = null;\n }\n this.events = null;\n this.config = null;\n this.initializationPromise = null; // Reset promise for clean re-initialization\n }\n}\n\nexport { GlobalAuthManager };\n"]}
|
package/dist/shared/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "@civic/auth:0.15.
|
|
1
|
+
export declare const VERSION = "@civic/auth:0.15.3";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/shared/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/shared/version.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAE/C,MAAM,CAAC,MAAM,OAAO,GAAG,oBAAoB,CAAC","sourcesContent":["// This is an auto-generated file. Do not edit.\n\nexport const VERSION = \"@civic/auth:0.15.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/shared/version.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAE/C,MAAM,CAAC,MAAM,OAAO,GAAG,oBAAoB,CAAC","sourcesContent":["// This is an auto-generated file. Do not edit.\n\nexport const VERSION = \"@civic/auth:0.15.3\";\n"]}
|