@civic/auth 0.7.0 → 0.7.1-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 +5 -0
- package/README.md +19 -1
- package/dist/nextjs/config.d.ts +1 -0
- package/dist/nextjs/config.d.ts.map +1 -1
- package/dist/nextjs/config.js +1 -1
- package/dist/nextjs/config.js.map +1 -1
- package/dist/nextjs/hooks/useRefresh.d.ts.map +1 -1
- package/dist/nextjs/hooks/useRefresh.js +7 -1
- package/dist/nextjs/hooks/useRefresh.js.map +1 -1
- package/dist/nextjs/routeHandler.d.ts.map +1 -1
- package/dist/nextjs/routeHandler.js +7 -0
- package/dist/nextjs/routeHandler.js.map +1 -1
- package/dist/reactjs/components/SignInButton.d.ts.map +1 -1
- package/dist/reactjs/components/SignInButton.js +8 -3
- package/dist/reactjs/components/SignInButton.js.map +1 -1
- package/dist/reactjs/components/SignOutButton.d.ts.map +1 -1
- package/dist/reactjs/components/SignOutButton.js +3 -1
- package/dist/reactjs/components/SignOutButton.js.map +1 -1
- package/dist/reactjs/components/UserButton.d.ts.map +1 -1
- package/dist/reactjs/components/UserButton.js +11 -6
- package/dist/reactjs/components/UserButton.js.map +1 -1
- package/dist/reactjs/components/index.d.ts +5 -5
- package/dist/reactjs/components/index.d.ts.map +1 -1
- package/dist/reactjs/components/index.js +5 -5
- package/dist/reactjs/components/index.js.map +1 -1
- package/dist/reactjs/core/GlobalAuthManager.d.ts +120 -0
- package/dist/reactjs/core/GlobalAuthManager.d.ts.map +1 -0
- package/dist/reactjs/core/GlobalAuthManager.js +296 -0
- package/dist/reactjs/core/GlobalAuthManager.js.map +1 -0
- package/dist/reactjs/hooks/index.d.ts +2 -2
- package/dist/reactjs/hooks/index.d.ts.map +1 -1
- package/dist/reactjs/hooks/index.js +2 -2
- package/dist/reactjs/hooks/index.js.map +1 -1
- package/dist/reactjs/hooks/useToken.d.ts +13 -0
- package/dist/reactjs/hooks/useToken.d.ts.map +1 -0
- package/dist/reactjs/hooks/useToken.js +48 -0
- package/dist/reactjs/hooks/useToken.js.map +1 -0
- package/dist/reactjs/hooks/useUser.d.ts +20 -2
- package/dist/reactjs/hooks/useUser.d.ts.map +1 -1
- package/dist/reactjs/hooks/useUser.js +163 -7
- package/dist/reactjs/hooks/useUser.js.map +1 -1
- package/dist/reactjs/index.d.ts +6 -2
- package/dist/reactjs/index.d.ts.map +1 -1
- package/dist/reactjs/index.js +7 -1
- package/dist/reactjs/index.js.map +1 -1
- package/dist/reactjs/providers/CivicAuthContext.d.ts +40 -0
- package/dist/reactjs/providers/CivicAuthContext.d.ts.map +1 -0
- package/dist/reactjs/providers/CivicAuthContext.js +303 -0
- package/dist/reactjs/providers/CivicAuthContext.js.map +1 -0
- package/dist/reactjs/providers/CivicAuthProvider.d.ts +20 -4
- package/dist/reactjs/providers/CivicAuthProvider.d.ts.map +1 -1
- package/dist/reactjs/providers/CivicAuthProvider.js +46 -25
- package/dist/reactjs/providers/CivicAuthProvider.js.map +1 -1
- package/dist/reactjs/providers/index.d.ts +2 -2
- package/dist/reactjs/providers/index.d.ts.map +1 -1
- package/dist/reactjs/providers/index.js +4 -2
- package/dist/reactjs/providers/index.js.map +1 -1
- package/dist/server/ServerAuthenticationResolver.d.ts.map +1 -1
- package/dist/server/ServerAuthenticationResolver.js +28 -11
- package/dist/server/ServerAuthenticationResolver.js.map +1 -1
- package/dist/server/config.d.ts +2 -0
- package/dist/server/config.d.ts.map +1 -1
- package/dist/server/config.js.map +1 -1
- package/dist/server/login.d.ts +2 -2
- package/dist/server/login.d.ts.map +1 -1
- package/dist/server/login.js +7 -2
- package/dist/server/login.js.map +1 -1
- package/dist/services/AuthenticationService.d.ts +1 -1
- package/dist/services/AuthenticationService.d.ts.map +1 -1
- package/dist/services/AuthenticationService.js +2 -2
- package/dist/services/AuthenticationService.js.map +1 -1
- package/dist/shared/components/CivicAuthIframe.js +1 -1
- package/dist/shared/components/CivicAuthIframe.js.map +1 -1
- package/dist/shared/components/CivicAuthIframeContainer.js +2 -2
- package/dist/shared/components/CivicAuthIframeContainer.js.map +1 -1
- 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/useClientTokenExchangeSession.d.ts +7 -0
- package/dist/shared/hooks/useClientTokenExchangeSession.d.ts.map +1 -0
- package/dist/shared/hooks/useClientTokenExchangeSession.js +17 -0
- package/dist/shared/hooks/useClientTokenExchangeSession.js.map +1 -0
- package/dist/shared/lib/BrowserAuthenticationRefresher.js +3 -3
- package/dist/shared/lib/BrowserAuthenticationRefresher.js.map +1 -1
- package/dist/shared/lib/types.d.ts +1 -1
- package/dist/shared/lib/types.js +1 -1
- package/dist/shared/lib/types.js.map +1 -1
- package/dist/shared/lib/util.d.ts +5 -6
- package/dist/shared/lib/util.d.ts.map +1 -1
- package/dist/shared/lib/util.js +66 -75
- package/dist/shared/lib/util.js.map +1 -1
- package/dist/shared/providers/CivicAuthConfigContext.d.ts +2 -2
- package/dist/shared/providers/CivicAuthConfigContext.d.ts.map +1 -1
- package/dist/shared/providers/CivicAuthConfigContext.js +1 -1
- package/dist/shared/providers/CivicAuthConfigContext.js.map +1 -1
- package/dist/shared/providers/TokenProvider.d.ts.map +1 -1
- package/dist/shared/providers/TokenProvider.js +4 -7
- package/dist/shared/providers/TokenProvider.js.map +1 -1
- 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/types.d.ts +2 -2
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +8 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +23 -0
- package/dist/utils.js.map +1 -1
- package/dist/vanillajs/auth/CivicAuth.d.ts +12 -0
- package/dist/vanillajs/auth/CivicAuth.d.ts.map +1 -1
- package/dist/vanillajs/auth/CivicAuth.js +88 -5
- package/dist/vanillajs/auth/CivicAuth.js.map +1 -1
- package/dist/vanillajs/auth/SessionManager.d.ts +7 -1
- package/dist/vanillajs/auth/SessionManager.d.ts.map +1 -1
- package/dist/vanillajs/auth/SessionManager.js +34 -3
- package/dist/vanillajs/auth/SessionManager.js.map +1 -1
- package/dist/vanillajs/auth/TokenRefresher.js +2 -2
- package/dist/vanillajs/auth/TokenRefresher.js.map +1 -1
- package/dist/vanillajs/auth/config/ConfigProcessor.d.ts.map +1 -1
- package/dist/vanillajs/auth/config/ConfigProcessor.js +7 -2
- package/dist/vanillajs/auth/config/ConfigProcessor.js.map +1 -1
- package/dist/vanillajs/auth/types/AuthTypes.d.ts +3 -0
- package/dist/vanillajs/auth/types/AuthTypes.d.ts.map +1 -1
- package/dist/vanillajs/auth/types/AuthTypes.js.map +1 -1
- package/dist/vanillajs/index.d.ts +2 -0
- package/dist/vanillajs/index.d.ts.map +1 -1
- package/dist/vanillajs/index.js +2 -0
- package/dist/vanillajs/index.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.map +1 -1
- package/dist/vanillajs/utils/auth-utils.d.ts +14 -0
- package/dist/vanillajs/utils/auth-utils.d.ts.map +1 -1
- package/dist/vanillajs/utils/auth-utils.js +39 -0
- package/dist/vanillajs/utils/auth-utils.js.map +1 -1
- package/package.json +3 -3
- package/dist/reactjs/hooks/useClientTokenExchangeSession.d.ts +0 -3
- package/dist/reactjs/hooks/useClientTokenExchangeSession.d.ts.map +0 -1
- package/dist/reactjs/hooks/useClientTokenExchangeSession.js +0 -13
- package/dist/reactjs/hooks/useClientTokenExchangeSession.js.map +0 -1
- package/dist/reactjs/providers/AuthProvider.d.ts +0 -10
- package/dist/reactjs/providers/AuthProvider.d.ts.map +0 -1
- package/dist/reactjs/providers/AuthProvider.js +0 -79
- package/dist/reactjs/providers/AuthProvider.js.map +0 -1
- package/dist/reactjs/providers/ClientTokenExchangeSessionProvider.d.ts +0 -17
- package/dist/reactjs/providers/ClientTokenExchangeSessionProvider.d.ts.map +0 -1
- package/dist/reactjs/providers/ClientTokenExchangeSessionProvider.js +0 -190
- package/dist/reactjs/providers/ClientTokenExchangeSessionProvider.js.map +0 -1
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
3
|
-
import React, { useEffect, useMemo, useState } from "react";
|
|
4
|
-
import {} from "../../types.js";
|
|
5
|
-
import { AuthContext } from "../../shared/providers/AuthContext.js";
|
|
6
|
-
import { useSignIn } from "../../shared/hooks/useSignIn.js";
|
|
7
|
-
import { useCivicAuthConfig } from "../../shared/hooks/useCivicAuthConfig.js";
|
|
8
|
-
import { useSession } from "../../shared/hooks/useSession.js";
|
|
9
|
-
import { IFrameAndLoading } from "../../shared/components/IFrameAndLoading.js";
|
|
10
|
-
import { useIsInIframe } from "../../shared/hooks/useIsInIframe.js";
|
|
11
|
-
import { useRefresh } from "../../shared/hooks/useRefresh.js";
|
|
12
|
-
// Global this object setup
|
|
13
|
-
let globalThisObject;
|
|
14
|
-
if (typeof window !== "undefined") {
|
|
15
|
-
globalThisObject = window;
|
|
16
|
-
}
|
|
17
|
-
else if (typeof global !== "undefined") {
|
|
18
|
-
globalThisObject = global;
|
|
19
|
-
}
|
|
20
|
-
else {
|
|
21
|
-
globalThisObject = Function("return this")();
|
|
22
|
-
}
|
|
23
|
-
globalThisObject.globalThis = globalThisObject;
|
|
24
|
-
const AuthProvider = ({ children, onSignIn, onSignOut, pkceConsumer, displayMode = "iframe", }) => {
|
|
25
|
-
const authConfig = useCivicAuthConfig();
|
|
26
|
-
const { signIn, signOut, authStatus } = useSignIn({
|
|
27
|
-
preSignOut: onSignOut,
|
|
28
|
-
pkceConsumer,
|
|
29
|
-
displayMode,
|
|
30
|
-
});
|
|
31
|
-
const [localSessionData, setLocalSessionData] = useState();
|
|
32
|
-
const { data: session, error: tokenExchangeError, isLoading: tokenExchangeInProgress, } = useSession();
|
|
33
|
-
useEffect(() => {
|
|
34
|
-
if (session) {
|
|
35
|
-
setLocalSessionData(session);
|
|
36
|
-
if (session.authenticated) {
|
|
37
|
-
onSignIn?.();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}, [onSignIn, session]);
|
|
41
|
-
const isAuthenticated = useMemo(() => {
|
|
42
|
-
return !!localSessionData?.idToken;
|
|
43
|
-
}, [localSessionData]);
|
|
44
|
-
// The startSignIn functionality has been moved to ClientTokenExchangeSessionProvider
|
|
45
|
-
// to prevent race conditions with validateExistingSession
|
|
46
|
-
const isInIframe = useIsInIframe();
|
|
47
|
-
// if the SDK loads in an iframe, we show the loading spinner until we know the auth state
|
|
48
|
-
// but don't keep showing it indefinitely if it's just the isInIframe status
|
|
49
|
-
const isLoading = tokenExchangeInProgress ||
|
|
50
|
-
!authConfig ||
|
|
51
|
-
(isInIframe && !localSessionData?.authenticated);
|
|
52
|
-
const { error: refreshError } = useRefresh(session);
|
|
53
|
-
useEffect(() => {
|
|
54
|
-
if (refreshError) {
|
|
55
|
-
console.error("Error refreshing token, signingOut...", refreshError);
|
|
56
|
-
signOut();
|
|
57
|
-
}
|
|
58
|
-
}, [refreshError, signOut]);
|
|
59
|
-
const value = useMemo(() => ({
|
|
60
|
-
isLoading,
|
|
61
|
-
error: tokenExchangeError,
|
|
62
|
-
signOut,
|
|
63
|
-
authStatus,
|
|
64
|
-
isAuthenticated,
|
|
65
|
-
signIn,
|
|
66
|
-
displayMode,
|
|
67
|
-
}), [
|
|
68
|
-
isLoading,
|
|
69
|
-
tokenExchangeError,
|
|
70
|
-
signOut,
|
|
71
|
-
authStatus,
|
|
72
|
-
isAuthenticated,
|
|
73
|
-
signIn,
|
|
74
|
-
displayMode,
|
|
75
|
-
]);
|
|
76
|
-
return (_jsxs(AuthContext.Provider, { value: value, children: [_jsx(IFrameAndLoading, { error: tokenExchangeError, isLoading: isLoading }), children] }));
|
|
77
|
-
};
|
|
78
|
-
export { AuthProvider };
|
|
79
|
-
//# sourceMappingURL=AuthProvider.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AuthProvider.js","sourceRoot":"","sources":["../../../src/reactjs/providers/AuthProvider.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\nimport React, { useEffect, useMemo, useState } from \"react\";\nimport { type SessionData } from \"@/types.js\";\nimport { AuthContext } from \"@/shared/providers/AuthContext.js\";\nimport type { PKCEConsumer } from \"@/services/types.js\";\nimport { useSignIn } from \"@/shared/hooks/useSignIn.js\";\nimport { useCivicAuthConfig } from \"@/shared/hooks/useCivicAuthConfig.js\";\nimport { useSession } from \"@/shared/hooks/useSession.js\";\nimport { IFrameAndLoading } from \"@/shared/components/IFrameAndLoading.js\";\nimport type { AuthProviderProps } from \"@/shared/providers/types.js\";\nimport { useIsInIframe } from \"@/shared/hooks/useIsInIframe.js\";\nimport { useRefresh } from \"@/shared/hooks/useRefresh.js\";\n\n// Global this object setup\nlet globalThisObject;\nif (typeof window !== \"undefined\") {\n globalThisObject = window;\n} else if (typeof global !== \"undefined\") {\n globalThisObject = global;\n} else {\n globalThisObject = Function(\"return this\")();\n}\nglobalThisObject.globalThis = globalThisObject;\n\nexport type InternalAuthProviderProps = AuthProviderProps & {\n sessionData?: SessionData;\n pkceConsumer?: PKCEConsumer;\n};\n\nconst AuthProvider = ({\n children,\n onSignIn,\n onSignOut,\n pkceConsumer,\n displayMode = \"iframe\",\n}: InternalAuthProviderProps) => {\n const authConfig = useCivicAuthConfig();\n const { signIn, signOut, authStatus } = useSignIn({\n preSignOut: onSignOut,\n pkceConsumer,\n displayMode,\n });\n\n const [localSessionData, setLocalSessionData] =\n useState<SessionData | null>();\n\n const {\n data: session,\n error: tokenExchangeError,\n isLoading: tokenExchangeInProgress,\n } = useSession();\n\n useEffect(() => {\n if (session) {\n setLocalSessionData(session);\n if (session.authenticated) {\n onSignIn?.();\n }\n }\n }, [onSignIn, session]);\n\n const isAuthenticated = useMemo(() => {\n return !!localSessionData?.idToken;\n }, [localSessionData]);\n\n // The startSignIn functionality has been moved to ClientTokenExchangeSessionProvider\n // to prevent race conditions with validateExistingSession\n\n const isInIframe = useIsInIframe();\n // if the SDK loads in an iframe, we show the loading spinner until we know the auth state\n // but don't keep showing it indefinitely if it's just the isInIframe status\n const isLoading =\n tokenExchangeInProgress ||\n !authConfig ||\n (isInIframe && !localSessionData?.authenticated);\n\n const { error: refreshError } = useRefresh(session);\n\n useEffect(() => {\n if (refreshError) {\n console.error(\"Error refreshing token, signingOut...\", refreshError);\n signOut();\n }\n }, [refreshError, signOut]);\n\n const value = useMemo(\n () => ({\n isLoading,\n error: tokenExchangeError as Error | null,\n signOut,\n authStatus,\n isAuthenticated,\n signIn,\n displayMode,\n }),\n [\n isLoading,\n tokenExchangeError,\n signOut,\n authStatus,\n isAuthenticated,\n signIn,\n displayMode,\n ],\n );\n\n return (\n <AuthContext.Provider value={value}>\n <IFrameAndLoading error={tokenExchangeError} isLoading={isLoading} />\n {children}\n </AuthContext.Provider>\n );\n};\n\nexport { AuthProvider };\n"]}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
2
|
-
import React from "react";
|
|
3
|
-
import { type SessionData } from "../../types.js";
|
|
4
|
-
export type ClientTokenExchangeSessionProviderOutput = {
|
|
5
|
-
data: SessionData | null;
|
|
6
|
-
error: Error | null;
|
|
7
|
-
isLoading: boolean;
|
|
8
|
-
doTokenExchange: null | ((url: string) => Promise<void>);
|
|
9
|
-
};
|
|
10
|
-
declare const ClientTokenExchangeSessionContext: React.Context<ClientTokenExchangeSessionProviderOutput>;
|
|
11
|
-
type ClientTokenExchangeSessionContextType = {
|
|
12
|
-
children: ReactNode;
|
|
13
|
-
};
|
|
14
|
-
declare const ClientTokenExchangeSessionProvider: ({ children, }: ClientTokenExchangeSessionContextType) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
15
|
-
export type { ClientTokenExchangeSessionContextType as SessionContextType };
|
|
16
|
-
export { ClientTokenExchangeSessionProvider, ClientTokenExchangeSessionContext, };
|
|
17
|
-
//# sourceMappingURL=ClientTokenExchangeSessionProvider.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ClientTokenExchangeSessionProvider.d.ts","sourceRoot":"","sources":["../../../src/reactjs/providers/ClientTokenExchangeSessionProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAON,MAAM,OAAO,CAAC;AAIf,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAU1D,MAAM,MAAM,wCAAwC,GAAG;IACrD,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;CAC1D,CAAC;AAcF,QAAA,MAAM,iCAAiC,yDACkC,CAAC;AAE1E,KAAK,qCAAqC,GAAG;IAC3C,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF,QAAA,MAAM,kCAAkC,kBAErC,qCAAqC,qDAyMvC,CAAC;AAEF,YAAY,EAAE,qCAAqC,IAAI,kBAAkB,EAAE,CAAC;AAC5E,OAAO,EACL,kCAAkC,EAClC,iCAAiC,GAClC,CAAC"}
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
3
|
-
import React, { createContext, useCallback, useEffect, useMemo, useState, useRef, } from "react";
|
|
4
|
-
import { BrowserAuthenticationService } from "../../services/AuthenticationService.js";
|
|
5
|
-
import { isWindowInIframe } from "../../lib/windowUtil.js";
|
|
6
|
-
import { AuthStatus } from "../../types.js";
|
|
7
|
-
import { useCurrentUrl, useCivicAuthConfig, useSignIn, useIframe, } from "../../shared/hooks/index.js";
|
|
8
|
-
import { LocalStorageAdapter } from "../../browser/storage.js";
|
|
9
|
-
import { getIframeRef } from "../../shared/lib/iframeUtils.js";
|
|
10
|
-
const defaultSession = {
|
|
11
|
-
data: {
|
|
12
|
-
authenticated: false,
|
|
13
|
-
idToken: undefined,
|
|
14
|
-
accessToken: undefined,
|
|
15
|
-
displayMode: "iframe",
|
|
16
|
-
},
|
|
17
|
-
error: null,
|
|
18
|
-
isLoading: false,
|
|
19
|
-
doTokenExchange: null,
|
|
20
|
-
};
|
|
21
|
-
// Context for exposing session specifically to the TokenProvider
|
|
22
|
-
const ClientTokenExchangeSessionContext = createContext(defaultSession);
|
|
23
|
-
const ClientTokenExchangeSessionProvider = ({ children, }) => {
|
|
24
|
-
const authConfig = useCivicAuthConfig();
|
|
25
|
-
const [authService, setAuthService] = useState();
|
|
26
|
-
const [error, setError] = useState(null);
|
|
27
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
28
|
-
const [session, setSession] = useState(null);
|
|
29
|
-
const { iframeRef } = useIframe();
|
|
30
|
-
const currentUrl = useCurrentUrl();
|
|
31
|
-
// Use the signIn hook with iframe displayMode
|
|
32
|
-
const { startSignIn, authStatus } = useSignIn({
|
|
33
|
-
displayMode: authConfig?.displayMode || "iframe",
|
|
34
|
-
});
|
|
35
|
-
// this state is used to track if the logout was triggered
|
|
36
|
-
// so that we disable auto-start signIn which won't work until the auth-server
|
|
37
|
-
// cookies have been fully cleared
|
|
38
|
-
const [logoutTriggered, setLogoutTriggered] = useState(false);
|
|
39
|
-
// Add a ref to track processed codes
|
|
40
|
-
const processedCodes = useRef(new Set());
|
|
41
|
-
useEffect(() => {
|
|
42
|
-
if (!currentUrl || !authConfig)
|
|
43
|
-
return;
|
|
44
|
-
const { redirectUrl, clientId, oauthServer, scopes, logoutRedirectUrl, logoutUrl, } = authConfig;
|
|
45
|
-
BrowserAuthenticationService.build({
|
|
46
|
-
clientId,
|
|
47
|
-
redirectUrl,
|
|
48
|
-
logoutRedirectUrl,
|
|
49
|
-
logoutUrl,
|
|
50
|
-
oauthServer,
|
|
51
|
-
scopes,
|
|
52
|
-
displayMode: "iframe",
|
|
53
|
-
}).then(setAuthService);
|
|
54
|
-
}, [currentUrl, authConfig]);
|
|
55
|
-
const isInIframe = isWindowInIframe(globalThis.window);
|
|
56
|
-
const doTokenExchange = useCallback(async (inUrl) => {
|
|
57
|
-
if (!authService)
|
|
58
|
-
return;
|
|
59
|
-
const url = new URL(inUrl);
|
|
60
|
-
const code = url.searchParams.get("code");
|
|
61
|
-
const state = url.searchParams.get("state");
|
|
62
|
-
// Create a unique key for this code/state combination
|
|
63
|
-
const exchangeKey = `${code}:${state}`;
|
|
64
|
-
// If we've already processed this code, skip it
|
|
65
|
-
if (processedCodes.current.has(exchangeKey)) {
|
|
66
|
-
console.log("Token exchange already processed for this code");
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
if (code && state) {
|
|
70
|
-
try {
|
|
71
|
-
// Mark this code as processed before starting the exchange
|
|
72
|
-
processedCodes.current.add(exchangeKey);
|
|
73
|
-
setIsLoading(true);
|
|
74
|
-
await authService.tokenExchange(code, state);
|
|
75
|
-
// Explicitly emit completion event after successful token exchange
|
|
76
|
-
LocalStorageAdapter.emitter.emit("civic-auth-signin-complete");
|
|
77
|
-
}
|
|
78
|
-
catch (error) {
|
|
79
|
-
setError(error);
|
|
80
|
-
setSession({ authenticated: false });
|
|
81
|
-
// Emit error event if exchange fails
|
|
82
|
-
LocalStorageAdapter.emitter.emit("civic-auth-signin-error", {
|
|
83
|
-
error,
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
setIsLoading(false);
|
|
87
|
-
}
|
|
88
|
-
}, [authService]);
|
|
89
|
-
const onSignIn = useCallback(async () => {
|
|
90
|
-
if (!authService)
|
|
91
|
-
return;
|
|
92
|
-
const session = await authService.getSessionData();
|
|
93
|
-
setSession(session);
|
|
94
|
-
}, [authService]);
|
|
95
|
-
const onSignOut = useCallback(() => {
|
|
96
|
-
setLogoutTriggered(true);
|
|
97
|
-
setSession(null);
|
|
98
|
-
}, []);
|
|
99
|
-
useEffect(() => {
|
|
100
|
-
LocalStorageAdapter.emitter.on("signIn", onSignIn);
|
|
101
|
-
LocalStorageAdapter.emitter.on("signOut", onSignOut);
|
|
102
|
-
return () => {
|
|
103
|
-
LocalStorageAdapter.emitter.off("signIn", onSignIn);
|
|
104
|
-
LocalStorageAdapter.emitter.off("signOut", onSignOut);
|
|
105
|
-
};
|
|
106
|
-
}, [onSignIn, onSignOut]);
|
|
107
|
-
useEffect(() => {
|
|
108
|
-
if (!authConfig) {
|
|
109
|
-
setIsLoading(true);
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
setIsLoading(false);
|
|
113
|
-
}
|
|
114
|
-
}, [authConfig]);
|
|
115
|
-
const [validationInProgress, setValidationInProgress] = useState(false);
|
|
116
|
-
// Handle page load or refocus
|
|
117
|
-
useEffect(() => {
|
|
118
|
-
if (!authConfig?.redirectUrl ||
|
|
119
|
-
!authService ||
|
|
120
|
-
!currentUrl ||
|
|
121
|
-
isInIframe ||
|
|
122
|
-
isLoading) {
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
// We specifically don't want to abort token refresh operations
|
|
126
|
-
// The AbortController is mainly used to prevent token exchange after unmount
|
|
127
|
-
const abortController = new AbortController();
|
|
128
|
-
const onPageLoad = async () => {
|
|
129
|
-
if (validationInProgress ||
|
|
130
|
-
authStatus === AuthStatus.SIGNING_OUT ||
|
|
131
|
-
authStatus === AuthStatus.AUTHENTICATING)
|
|
132
|
-
return;
|
|
133
|
-
// if we have existing tokens, then validate them and return the session data
|
|
134
|
-
// otherwise check if we have a code in the url and exchange it for tokens
|
|
135
|
-
// if we have neither, initiate sign-in flow
|
|
136
|
-
setValidationInProgress(true);
|
|
137
|
-
try {
|
|
138
|
-
const existingSessionData = await authService.validateExistingSession();
|
|
139
|
-
if (existingSessionData.authenticated) {
|
|
140
|
-
setSession(existingSessionData);
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
// If we have a code in the URL, attempt token exchange
|
|
144
|
-
if (new URL(currentUrl).searchParams.get("code")) {
|
|
145
|
-
await doTokenExchange(currentUrl);
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
// No valid session and no code in URL - initiate sign-in
|
|
149
|
-
// But only if we're not in an iframe (to prevent infinite loops in embedded scenarios)
|
|
150
|
-
if (!isInIframe && authConfig) {
|
|
151
|
-
const ref = getIframeRef(iframeRef?.current, true);
|
|
152
|
-
// if logout was triggered, we don't want to auto-start sign-in
|
|
153
|
-
// as the auth-server cookies will not be cleared yet
|
|
154
|
-
if (ref && authConfig?.displayMode === "iframe" && !logoutTriggered) {
|
|
155
|
-
startSignIn();
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
catch (error) {
|
|
160
|
-
console.error("Error during session validation:", error);
|
|
161
|
-
}
|
|
162
|
-
finally {
|
|
163
|
-
setValidationInProgress(false);
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
onPageLoad();
|
|
167
|
-
return () => {
|
|
168
|
-
abortController.abort();
|
|
169
|
-
};
|
|
170
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
171
|
-
}, [
|
|
172
|
-
authConfig,
|
|
173
|
-
authService,
|
|
174
|
-
currentUrl,
|
|
175
|
-
doTokenExchange,
|
|
176
|
-
isInIframe,
|
|
177
|
-
isLoading,
|
|
178
|
-
startSignIn,
|
|
179
|
-
logoutTriggered,
|
|
180
|
-
]);
|
|
181
|
-
const value = useMemo(() => ({
|
|
182
|
-
data: session,
|
|
183
|
-
error,
|
|
184
|
-
isLoading,
|
|
185
|
-
doTokenExchange: authService ? doTokenExchange : null,
|
|
186
|
-
}), [session, error, isLoading, authService, doTokenExchange]);
|
|
187
|
-
return (_jsx(ClientTokenExchangeSessionContext.Provider, { value: value, children: children }));
|
|
188
|
-
};
|
|
189
|
-
export { ClientTokenExchangeSessionProvider, ClientTokenExchangeSessionContext, };
|
|
190
|
-
//# sourceMappingURL=ClientTokenExchangeSessionProvider.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ClientTokenExchangeSessionProvider.js","sourceRoot":"","sources":["../../../src/reactjs/providers/ClientTokenExchangeSessionProvider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,KAAK,EAAE,EACZ,aAAa,EACb,WAAW,EACX,SAAS,EACT,OAAO,EACP,QAAQ,EACR,MAAM,GACP,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;AAEnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAoB,MAAM,YAAY,CAAC;AAC1D,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,SAAS,EACT,SAAS,GACV,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAQ3D,MAAM,cAAc,GAA6C;IAC/D,IAAI,EAAE;QACJ,aAAa,EAAE,KAAK;QACpB,OAAO,EAAE,SAAS;QAClB,WAAW,EAAE,SAAS;QACtB,WAAW,EAAE,QAAQ;KACtB;IACD,KAAK,EAAE,IAAI;IACX,SAAS,EAAE,KAAK;IAChB,eAAe,EAAE,IAAI;CACtB,CAAC;AAEF,iEAAiE;AACjE,MAAM,iCAAiC,GACrC,aAAa,CAA2C,cAAc,CAAC,CAAC;AAM1E,MAAM,kCAAkC,GAAG,CAAC,EAC1C,QAAQ,GAC8B,EAAE,EAAE;IAC1C,MAAM,UAAU,GAAG,kBAAkB,EAAE,CAAC;IACxC,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,EAA0B,CAAC;IACzE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IACvD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAqB,IAAI,CAAC,CAAC;IACjE,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAAC;IAClC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,8CAA8C;IAC9C,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,SAAS,CAAC;QAC5C,WAAW,EAAE,UAAU,EAAE,WAAW,IAAI,QAAQ;KACjD,CAAC,CAAC;IACH,0DAA0D;IAC1D,8EAA8E;IAC9E,kCAAkC;IAClC,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE9D,qCAAqC;IACrC,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,GAAG,EAAU,CAAC,CAAC;IAEjD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU;YAAE,OAAO;QAEvC,MAAM,EACJ,WAAW,EACX,QAAQ,EACR,WAAW,EACX,MAAM,EACN,iBAAiB,EACjB,SAAS,GACV,GAAG,UAAU,CAAC;QACf,4BAA4B,CAAC,KAAK,CAAC;YACjC,QAAQ;YACR,WAAW;YACX,iBAAiB;YACjB,SAAS;YACT,WAAW;YACX,MAAM;YACN,WAAW,EAAE,QAAQ;SACtB,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1B,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;IAE7B,MAAM,UAAU,GAAG,gBAAgB,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAEvD,MAAM,eAAe,GAAG,WAAW,CACjC,KAAK,EAAE,KAAa,EAAE,EAAE;QACtB,IAAI,CAAC,WAAW;YAAE,OAAO;QACzB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3B,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAE5C,sDAAsD;QACtD,MAAM,WAAW,GAAG,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC;QAEvC,gDAAgD;QAChD,IAAI,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;YAC9D,OAAO;QACT,CAAC;QAED,IAAI,IAAI,IAAI,KAAK,EAAE,CAAC;YAClB,IAAI,CAAC;gBACH,2DAA2D;gBAC3D,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBACxC,YAAY,CAAC,IAAI,CAAC,CAAC;gBACnB,MAAM,WAAW,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBAC7C,mEAAmE;gBACnE,mBAAmB,CAAC,OAAO,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;YACjE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,QAAQ,CAAC,KAAc,CAAC,CAAC;gBACzB,UAAU,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;gBACrC,qCAAqC;gBACrC,mBAAmB,CAAC,OAAO,CAAC,IAAI,CAAC,yBAAyB,EAAE;oBAC1D,KAAK;iBACN,CAAC,CAAC;YACL,CAAC;YACD,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,EACD,CAAC,WAAW,CAAC,CACd,CAAC;IAEF,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACtC,IAAI,CAAC,WAAW;YAAE,OAAO;QACzB,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,cAAc,EAAE,CAAC;QACnD,UAAU,CAAC,OAAO,CAAC,CAAC;IACtB,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;QACjC,kBAAkB,CAAC,IAAI,CAAC,CAAC;QACzB,UAAU,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,SAAS,CAAC,GAAG,EAAE;QACb,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACnD,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACrD,OAAO,GAAG,EAAE;YACV,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACpD,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACxD,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;IAE1B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,YAAY,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjB,MAAM,CAAC,oBAAoB,EAAE,uBAAuB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxE,8BAA8B;IAC9B,SAAS,CAAC,GAAG,EAAE;QACb,IACE,CAAC,UAAU,EAAE,WAAW;YACxB,CAAC,WAAW;YACZ,CAAC,UAAU;YACX,UAAU;YACV,SAAS,EACT,CAAC;YACD,OAAO;QACT,CAAC;QAED,+DAA+D;QAC/D,6EAA6E;QAC7E,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QAE9C,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE;YAC5B,IACE,oBAAoB;gBACpB,UAAU,KAAK,UAAU,CAAC,WAAW;gBACrC,UAAU,KAAK,UAAU,CAAC,cAAc;gBAExC,OAAO;YAET,6EAA6E;YAC7E,0EAA0E;YAC1E,4CAA4C;YAC5C,uBAAuB,CAAC,IAAI,CAAC,CAAC;YAE9B,IAAI,CAAC;gBACH,MAAM,mBAAmB,GAAG,MAAM,WAAW,CAAC,uBAAuB,EAAE,CAAC;gBAExE,IAAI,mBAAmB,CAAC,aAAa,EAAE,CAAC;oBACtC,UAAU,CAAC,mBAAmB,CAAC,CAAC;oBAChC,OAAO;gBACT,CAAC;gBACD,uDAAuD;gBACvD,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;oBACjD,MAAM,eAAe,CAAC,UAAU,CAAC,CAAC;oBAClC,OAAO;gBACT,CAAC;gBACD,yDAAyD;gBACzD,uFAAuF;gBACvF,IAAI,CAAC,UAAU,IAAI,UAAU,EAAE,CAAC;oBAC9B,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;oBACnD,+DAA+D;oBAC/D,qDAAqD;oBACrD,IAAI,GAAG,IAAI,UAAU,EAAE,WAAW,KAAK,QAAQ,IAAI,CAAC,eAAe,EAAE,CAAC;wBACpE,WAAW,EAAE,CAAC;oBAChB,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;YAC3D,CAAC;oBAAS,CAAC;gBACT,uBAAuB,CAAC,KAAK,CAAC,CAAC;YACjC,CAAC;QACH,CAAC,CAAC;QAEF,UAAU,EAAE,CAAC;QAEb,OAAO,GAAG,EAAE;YACV,eAAe,CAAC,KAAK,EAAE,CAAC;QAC1B,CAAC,CAAC;QACF,uDAAuD;IACzD,CAAC,EAAE;QACD,UAAU;QACV,WAAW;QACX,UAAU;QACV,eAAe;QACf,UAAU;QACV,SAAS;QACT,WAAW;QACX,eAAe;KAChB,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,CAAC;QACL,IAAI,EAAE,OAAO;QACb,KAAK;QACL,SAAS;QACT,eAAe,EAAE,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI;KACtD,CAAC,EACF,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,CAAC,CAC1D,CAAC;IAEF,OAAO,CACL,KAAC,iCAAiC,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YACrD,QAAQ,GACkC,CAC9C,CAAC;AACJ,CAAC,CAAC;AAGF,OAAO,EACL,kCAAkC,EAClC,iCAAiC,GAClC,CAAC","sourcesContent":["\"use client\";\nimport type { ReactNode } from \"react\";\nimport React, {\n createContext,\n useCallback,\n useEffect,\n useMemo,\n useState,\n useRef,\n} from \"react\";\nimport { BrowserAuthenticationService } from \"@/services/AuthenticationService.js\";\nimport type { AuthenticationResolver } from \"@/services/types.js\";\nimport { isWindowInIframe } from \"@/lib/windowUtil.js\";\nimport { AuthStatus, type SessionData } from \"@/types.js\";\nimport {\n useCurrentUrl,\n useCivicAuthConfig,\n useSignIn,\n useIframe,\n} from \"@/shared/hooks/index.js\";\nimport { LocalStorageAdapter } from \"@/browser/storage.js\";\nimport { getIframeRef } from \"@/shared/lib/iframeUtils.js\";\n\nexport type ClientTokenExchangeSessionProviderOutput = {\n data: SessionData | null;\n error: Error | null;\n isLoading: boolean;\n doTokenExchange: null | ((url: string) => Promise<void>);\n};\nconst defaultSession: ClientTokenExchangeSessionProviderOutput = {\n data: {\n authenticated: false,\n idToken: undefined,\n accessToken: undefined,\n displayMode: \"iframe\",\n },\n error: null,\n isLoading: false,\n doTokenExchange: null,\n};\n\n// Context for exposing session specifically to the TokenProvider\nconst ClientTokenExchangeSessionContext =\n createContext<ClientTokenExchangeSessionProviderOutput>(defaultSession);\n\ntype ClientTokenExchangeSessionContextType = {\n children: ReactNode;\n};\n\nconst ClientTokenExchangeSessionProvider = ({\n children,\n}: ClientTokenExchangeSessionContextType) => {\n const authConfig = useCivicAuthConfig();\n const [authService, setAuthService] = useState<AuthenticationResolver>();\n const [error, setError] = useState<Error | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [session, setSession] = useState<SessionData | null>(null);\n const { iframeRef } = useIframe();\n const currentUrl = useCurrentUrl();\n // Use the signIn hook with iframe displayMode\n const { startSignIn, authStatus } = useSignIn({\n displayMode: authConfig?.displayMode || \"iframe\",\n });\n // this state is used to track if the logout was triggered\n // so that we disable auto-start signIn which won't work until the auth-server\n // cookies have been fully cleared\n const [logoutTriggered, setLogoutTriggered] = useState(false);\n\n // Add a ref to track processed codes\n const processedCodes = useRef(new Set<string>());\n\n useEffect(() => {\n if (!currentUrl || !authConfig) return;\n\n const {\n redirectUrl,\n clientId,\n oauthServer,\n scopes,\n logoutRedirectUrl,\n logoutUrl,\n } = authConfig;\n BrowserAuthenticationService.build({\n clientId,\n redirectUrl,\n logoutRedirectUrl,\n logoutUrl,\n oauthServer,\n scopes,\n displayMode: \"iframe\",\n }).then(setAuthService);\n }, [currentUrl, authConfig]);\n\n const isInIframe = isWindowInIframe(globalThis.window);\n\n const doTokenExchange = useCallback(\n async (inUrl: string) => {\n if (!authService) return;\n const url = new URL(inUrl);\n const code = url.searchParams.get(\"code\");\n const state = url.searchParams.get(\"state\");\n\n // Create a unique key for this code/state combination\n const exchangeKey = `${code}:${state}`;\n\n // If we've already processed this code, skip it\n if (processedCodes.current.has(exchangeKey)) {\n console.log(\"Token exchange already processed for this code\");\n return;\n }\n\n if (code && state) {\n try {\n // Mark this code as processed before starting the exchange\n processedCodes.current.add(exchangeKey);\n setIsLoading(true);\n await authService.tokenExchange(code, state);\n // Explicitly emit completion event after successful token exchange\n LocalStorageAdapter.emitter.emit(\"civic-auth-signin-complete\");\n } catch (error) {\n setError(error as Error);\n setSession({ authenticated: false });\n // Emit error event if exchange fails\n LocalStorageAdapter.emitter.emit(\"civic-auth-signin-error\", {\n error,\n });\n }\n setIsLoading(false);\n }\n },\n [authService],\n );\n\n const onSignIn = useCallback(async () => {\n if (!authService) return;\n const session = await authService.getSessionData();\n setSession(session);\n }, [authService]);\n\n const onSignOut = useCallback(() => {\n setLogoutTriggered(true);\n setSession(null);\n }, []);\n\n useEffect(() => {\n LocalStorageAdapter.emitter.on(\"signIn\", onSignIn);\n LocalStorageAdapter.emitter.on(\"signOut\", onSignOut);\n return () => {\n LocalStorageAdapter.emitter.off(\"signIn\", onSignIn);\n LocalStorageAdapter.emitter.off(\"signOut\", onSignOut);\n };\n }, [onSignIn, onSignOut]);\n\n useEffect(() => {\n if (!authConfig) {\n setIsLoading(true);\n } else {\n setIsLoading(false);\n }\n }, [authConfig]);\n\n const [validationInProgress, setValidationInProgress] = useState(false);\n // Handle page load or refocus\n useEffect(() => {\n if (\n !authConfig?.redirectUrl ||\n !authService ||\n !currentUrl ||\n isInIframe ||\n isLoading\n ) {\n return;\n }\n\n // We specifically don't want to abort token refresh operations\n // The AbortController is mainly used to prevent token exchange after unmount\n const abortController = new AbortController();\n\n const onPageLoad = async () => {\n if (\n validationInProgress ||\n authStatus === AuthStatus.SIGNING_OUT ||\n authStatus === AuthStatus.AUTHENTICATING\n )\n return;\n\n // if we have existing tokens, then validate them and return the session data\n // otherwise check if we have a code in the url and exchange it for tokens\n // if we have neither, initiate sign-in flow\n setValidationInProgress(true);\n\n try {\n const existingSessionData = await authService.validateExistingSession();\n\n if (existingSessionData.authenticated) {\n setSession(existingSessionData);\n return;\n }\n // If we have a code in the URL, attempt token exchange\n if (new URL(currentUrl).searchParams.get(\"code\")) {\n await doTokenExchange(currentUrl);\n return;\n }\n // No valid session and no code in URL - initiate sign-in\n // But only if we're not in an iframe (to prevent infinite loops in embedded scenarios)\n if (!isInIframe && authConfig) {\n const ref = getIframeRef(iframeRef?.current, true);\n // if logout was triggered, we don't want to auto-start sign-in\n // as the auth-server cookies will not be cleared yet\n if (ref && authConfig?.displayMode === \"iframe\" && !logoutTriggered) {\n startSignIn();\n }\n }\n } catch (error) {\n console.error(\"Error during session validation:\", error);\n } finally {\n setValidationInProgress(false);\n }\n };\n\n onPageLoad();\n\n return () => {\n abortController.abort();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n authConfig,\n authService,\n currentUrl,\n doTokenExchange,\n isInIframe,\n isLoading,\n startSignIn,\n logoutTriggered,\n ]);\n\n const value = useMemo(\n () => ({\n data: session,\n error,\n isLoading,\n doTokenExchange: authService ? doTokenExchange : null,\n }),\n [session, error, isLoading, authService, doTokenExchange],\n );\n\n return (\n <ClientTokenExchangeSessionContext.Provider value={value}>\n {children}\n </ClientTokenExchangeSessionContext.Provider>\n );\n};\n\nexport type { ClientTokenExchangeSessionContextType as SessionContextType };\nexport {\n ClientTokenExchangeSessionProvider,\n ClientTokenExchangeSessionContext,\n};\n"]}
|